@@ -18,11 +18,10 @@ class Auth:
18
18
To implement a custom authentication scheme, subclass `Auth` and override
19
19
the `.auth_flow()` method.
20
20
21
- If the authentication scheme does I/O, such as disk access or network calls, or uses
22
- synchronization primitives such as locks, you should override `.async_auth_flow()`
23
- to provide an async-friendly implementation that will be used by the `AsyncClient`.
24
- Usage of sync I/O within an async codebase would block the event loop, and could
25
- cause performance issues.
21
+ If the authentication scheme does I/O such as disk access or network calls, or uses
22
+ synchronization primitives such as locks, you should override `.sync_auth_flow()`
23
+ and/or `.async_auth_flow()` instead of `.auth_flow()` to provide specialized
24
+ implementations that will be used by `Client` and `AsyncClient` respectively.
26
25
"""
27
26
28
27
requires_request_body = False
@@ -50,7 +49,34 @@ def auth_flow(self, request: Request) -> typing.Generator[Request, Response, Non
50
49
51
50
You can dispatch as many requests as is necessary.
52
51
"""
53
- yield request
52
+ raise NotImplementedError (
53
+ "Override 'auth_flow' to implement a custom auth class."
54
+ ) # pragma: no cover
55
+
56
+ def sync_auth_flow (
57
+ self , request : Request
58
+ ) -> typing .Generator [Request , Response , None ]:
59
+ """
60
+ Execute the authentication flow synchronously.
61
+
62
+ By default, this defers to `.auth_flow()`. You should override this method
63
+ when the authentication scheme does I/O and/or uses concurrency primitives.
64
+ """
65
+ if self .requires_request_body :
66
+ request .read ()
67
+
68
+ flow = self .auth_flow (request )
69
+ request = next (flow )
70
+
71
+ while True :
72
+ response = yield request
73
+ if self .requires_response_body :
74
+ response .read ()
75
+
76
+ try :
77
+ request = flow .send (response )
78
+ except StopIteration :
79
+ break
54
80
55
81
async def async_auth_flow (
56
82
self , request : Request
@@ -59,20 +85,34 @@ async def async_auth_flow(
59
85
Execute the authentication flow asynchronously.
60
86
61
87
By default, this defers to `.auth_flow()`. You should override this method
62
- when the authentication scheme does I/O, such as disk access or network calls,
63
- or uses concurrency primitives such as locks.
88
+ when the authentication scheme does I/O and/or uses concurrency primitives.
64
89
"""
90
+ if self .requires_request_body :
91
+ await request .aread ()
92
+
65
93
flow = self .auth_flow (request )
66
94
request = next (flow )
67
95
68
96
while True :
69
97
response = yield request
98
+ if self .requires_response_body :
99
+ await response .aread ()
100
+
70
101
try :
71
102
request = flow .send (response )
72
103
except StopIteration :
73
104
break
74
105
75
106
107
+ class NoAuth (Auth ):
108
+ """
109
+ A 'do nothing' scheme for use when no authentication should be performed.
110
+ """
111
+
112
+ def auth_flow (self , request : Request ) -> typing .Generator [Request , Response , None ]:
113
+ yield request
114
+
115
+
76
116
class FunctionAuth (Auth ):
77
117
"""
78
118
Allows the 'auth' argument to be passed as a simple callable function,
0 commit comments