2
2
from __future__ import unicode_literals
3
3
from collections import OrderedDict
4
4
from coreapi import exceptions , utils
5
- from coreapi .compat import urlparse
5
+ from coreapi .compat import cookiejar , urlparse
6
6
from coreapi .document import Document , Object , Link , Array , Error
7
7
from coreapi .transports .base import BaseTransport
8
8
from coreapi .utils import guess_filename , is_file , File
11
11
import itypes
12
12
import mimetypes
13
13
import uritemplate
14
+ import warnings
14
15
15
16
16
17
Params = collections .namedtuple ('Params' , ['path' , 'query' , 'data' , 'files' ])
17
18
empty_params = Params ({}, {}, {}, {})
18
19
19
20
20
21
class ForceMultiPartDict (dict ):
21
- # A dictionary that always evaluates as True.
22
- # Allows us to force requests to use multipart encoding, even when no
23
- # file parameters are passed.
22
+ """
23
+ A dictionary that always evaluates as True.
24
+ Allows us to force requests to use multipart encoding, even when no
25
+ file parameters are passed.
26
+ """
24
27
def __bool__ (self ):
25
28
return True
26
29
27
30
def __nonzero__ (self ):
28
31
return True
29
32
30
33
34
+ class BlockAll (cookiejar .CookiePolicy ):
35
+ """
36
+ A cookie policy that rejects all cookies.
37
+ Used to override the default `requests` behavior.
38
+ """
39
+ return_ok = set_ok = domain_return_ok = path_return_ok = lambda self , * args , ** kwargs : False
40
+ netscape = True
41
+ rfc2965 = hide_cookie2 = False
42
+
43
+
44
+ class DomainCredentials (requests .auth .AuthBase ):
45
+ """
46
+ Custom auth class to support deprecated 'credentials' argument.
47
+ """
48
+ allow_cookies = False
49
+ credentials = None
50
+
51
+ def __init__ (self , credentials = None ):
52
+ self .credentials = credentials
53
+
54
+ def __call__ (self , request ):
55
+ if not self .credentials :
56
+ return request
57
+
58
+ # Include any authorization credentials relevant to this domain.
59
+ url_components = urlparse .urlparse (request .url )
60
+ host = url_components .hostname
61
+ if host in self .credentials :
62
+ request .headers ['Authorization' ] = self .credentials [host ]
63
+ return request
64
+
65
+
66
+ class CallbackAdapter (requests .adapters .HTTPAdapter ):
67
+ """
68
+ Custom requests HTTP adapter, to support deprecated callback arguments.
69
+ """
70
+ def __init__ (self , request_callback = None , response_callback = None ):
71
+ self .request_callback = request_callback
72
+ self .response_callback = response_callback
73
+
74
+ def send (self , request , ** kwargs ):
75
+ if self .request_callback is not None :
76
+ self .request_callback (request )
77
+ response = super (CallbackAdapter , self ).send (request , ** kwargs )
78
+ if self .response_callback is not None :
79
+ self .response_callback (response )
80
+ return response
81
+
82
+
31
83
def _get_method (action ):
32
84
if not action :
33
85
return 'GET'
@@ -107,7 +159,7 @@ def _get_url(url, path_params):
107
159
return url
108
160
109
161
110
- def _get_headers (url , decoders , credentials = None ):
162
+ def _get_headers (url , decoders ):
111
163
"""
112
164
Return a dictionary of HTTP headers to use in the outgoing request.
113
165
"""
@@ -120,13 +172,6 @@ def _get_headers(url, decoders, credentials=None):
120
172
'user-agent' : 'coreapi'
121
173
}
122
174
123
- if credentials :
124
- # Include any authorization credentials relevant to this domain.
125
- url_components = urlparse .urlparse (url )
126
- host = url_components .hostname
127
- if host in credentials :
128
- headers ['authorization' ] = credentials [host ]
129
-
130
175
return headers
131
176
132
177
@@ -288,24 +333,34 @@ def _handle_inplace_replacements(document, link, link_ancestors):
288
333
class HTTPTransport (BaseTransport ):
289
334
schemes = ['http' , 'https' ]
290
335
291
- def __init__ (self , credentials = None , headers = None , session = None , request_callback = None , response_callback = None ):
336
+ def __init__ (self , credentials = None , headers = None , auth = None , session = None , request_callback = None , response_callback = None ):
292
337
if headers :
293
338
headers = {key .lower (): value for key , value in headers .items ()}
294
339
if session is None :
295
340
session = requests .Session ()
296
- self ._credentials = itypes .Dict (credentials or {})
341
+ if auth is not None :
342
+ session .auth = auth
343
+ if not getattr (session .auth , 'allow_cookies' , False ):
344
+ session .cookies .set_policy (BlockAll ())
345
+
346
+ if credentials is not None :
347
+ warnings .warn (
348
+ "The 'credentials' argument is now deprecated in favor of 'auth'." ,
349
+ DeprecationWarning
350
+ )
351
+ auth = DomainCredentials (credentials )
352
+ if request_callback is not None or response_callback is not None :
353
+ warnings .warn (
354
+ "The 'request_callback' and 'response_callback' arguments are now deprecated. "
355
+ "Use a custom 'session' instance instead." ,
356
+ DeprecationWarning
357
+ )
358
+ session .mount ('https://' , CallbackAdapter (request_callback , response_callback ))
359
+ session .mount ('http://' , CallbackAdapter (request_callback , response_callback ))
360
+
297
361
self ._headers = itypes .Dict (headers or {})
298
362
self ._session = session
299
363
300
- # Fallback for v1.x overrides.
301
- # Will be removed at some point, most likely in a 2.1 release.
302
- self ._request_callback = request_callback
303
- self ._response_callback = response_callback
304
-
305
- @property
306
- def credentials (self ):
307
- return self ._credentials
308
-
309
364
@property
310
365
def headers (self ):
311
366
return self ._headers
@@ -316,19 +371,11 @@ def transition(self, link, decoders, params=None, link_ancestors=None, force_cod
316
371
encoding = _get_encoding (link .encoding )
317
372
params = _get_params (method , encoding , link .fields , params )
318
373
url = _get_url (link .url , params .path )
319
- headers = _get_headers (url , decoders , self . credentials )
374
+ headers = _get_headers (url , decoders )
320
375
headers .update (self .headers )
321
376
322
377
request = _build_http_request (session , url , method , headers , encoding , params )
323
-
324
- if self ._request_callback is not None :
325
- self ._request_callback (request )
326
-
327
378
response = session .send (request )
328
-
329
- if self ._response_callback is not None :
330
- self ._response_callback (response )
331
-
332
379
result = _decode_result (response , decoders , force_codec )
333
380
334
381
if isinstance (result , Document ) and link_ancestors :
0 commit comments