mirror of
https://github.com/kennethreitz/requests.git
synced 2026-06-05 22:50:18 +00:00
Merge settings when creating PreparedRequest, don't copy Request.
This commit is contained in:
+27
-32
@@ -28,8 +28,6 @@ from .compat import (
|
||||
cookielib, urlunparse, urlsplit, urlencode, str, bytes, StringIO,
|
||||
is_py2, chardet, json, builtin_str, basestring)
|
||||
|
||||
from copy import copy as shallowcopy
|
||||
|
||||
CONTENT_CHUNK_SIZE = 10 * 1024
|
||||
ITER_CHUNK_SIZE = 512
|
||||
|
||||
@@ -216,39 +214,20 @@ class Request(RequestHooksMixin):
|
||||
def __repr__(self):
|
||||
return '<Request [%s]>' % (self.method)
|
||||
|
||||
def copy(self):
|
||||
return Request(
|
||||
method = self.method,
|
||||
url = self.url,
|
||||
auth = self.auth,
|
||||
|
||||
# Copy mutable dict/list parameters so that altering one request
|
||||
# does not alter the copy.
|
||||
headers = shallowcopy(self.headers),
|
||||
params = shallowcopy(self.params),
|
||||
cookies = shallowcopy(self.cookies),
|
||||
hooks = shallowcopy(self.hooks),
|
||||
|
||||
files = shallowcopy(self.files),
|
||||
data = shallowcopy(self.data),
|
||||
)
|
||||
|
||||
def prepare(self):
|
||||
"""Constructs a :class:`PreparedRequest <PreparedRequest>` for transmission and returns it."""
|
||||
p = PreparedRequest()
|
||||
|
||||
p.prepare_method(self.method)
|
||||
p.prepare_url(self.url, self.params)
|
||||
p.prepare_headers(self.headers)
|
||||
p.prepare_cookies(self.cookies)
|
||||
p.prepare_body(self.data, self.files)
|
||||
p.prepare_auth(self.auth, self.url)
|
||||
# Note that prepare_auth must be last to enable authentication schemes
|
||||
# such as OAuth to work on a fully prepared request.
|
||||
|
||||
# This MUST go after prepare_auth. Authenticators could add a hook
|
||||
p.prepare_hooks(self.hooks)
|
||||
|
||||
p.prepare(
|
||||
method=self.method,
|
||||
url=self.url,
|
||||
headers=self.headers,
|
||||
files=self.files,
|
||||
data=self.data,
|
||||
params=self.params,
|
||||
auth=self.auth,
|
||||
cookies=self.cookies,
|
||||
hooks=self.hooks,
|
||||
)
|
||||
return p
|
||||
|
||||
|
||||
@@ -283,6 +262,22 @@ class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
|
||||
#: dictionary of callback hooks, for internal usage.
|
||||
self.hooks = default_hooks()
|
||||
|
||||
def prepare(self, method=None, url=None, headers=None, files=None,
|
||||
data=None, params=None, auth=None, cookies=None, hooks=None):
|
||||
"""Prepares the the entire request with the given parameters."""
|
||||
|
||||
self.prepare_method(method)
|
||||
self.prepare_url(url, params)
|
||||
self.prepare_headers(headers)
|
||||
self.prepare_cookies(cookies)
|
||||
self.prepare_body(data, files)
|
||||
self.prepare_auth(auth, url)
|
||||
# Note that prepare_auth must be last to enable authentication schemes
|
||||
# such as OAuth to work on a fully prepared request.
|
||||
|
||||
# This MUST go after prepare_auth. Authenticators could add a hook
|
||||
self.prepare_hooks(hooks)
|
||||
|
||||
def __repr__(self):
|
||||
return '<PreparedRequest [%s]>' % (self.method)
|
||||
|
||||
|
||||
+26
-23
@@ -228,11 +228,14 @@ class Session(SessionRedirectMixin):
|
||||
def __exit__(self, *args):
|
||||
self.close()
|
||||
|
||||
def update_request(self, request):
|
||||
"""Destructively updates/merges the settings of a :class:`Request`
|
||||
object from those of the :class:`Session`.
|
||||
def prepare_request(self, request):
|
||||
"""Constructs a :class:`PreparedRequest <PreparedRequest>` for
|
||||
transmission and returns it. The :class:`PreparedRequest` has settings
|
||||
merged from the :class:`Request <Request>` instance and those of the
|
||||
:class:`Session`.
|
||||
|
||||
:param request: mutable :class:`Request` instance.
|
||||
:param request: :class:`Request` instance to prepare with this
|
||||
session's settings.
|
||||
"""
|
||||
cookies = request.cookies or {}
|
||||
|
||||
@@ -244,25 +247,26 @@ class Session(SessionRedirectMixin):
|
||||
merged_cookies = RequestsCookieJar()
|
||||
merged_cookies.update(self.cookies)
|
||||
merged_cookies.update(cookies)
|
||||
request.cookies = merged_cookies
|
||||
|
||||
# Gather clues from the surrounding environment.
|
||||
if self.trust_env:
|
||||
# Set environment's basic authentication if not explicitly set.
|
||||
if not request.auth and not self.auth:
|
||||
request.auth = get_netrc_auth(request.url)
|
||||
|
||||
# Merge settings from the request and the session.
|
||||
request.params = merge_setting(request.params, self.params)
|
||||
request.headers = merge_setting(request.headers, self.headers, dict_class=CaseInsensitiveDict)
|
||||
request.auth = merge_setting(request.auth, self.auth)
|
||||
request.hooks = merge_setting(request.hooks, self.hooks)
|
||||
request.method = request.method.upper()
|
||||
# Set environment's basic authentication if not explicitly set.
|
||||
auth = request.auth
|
||||
if self.trust_env and not auth and not self.auth:
|
||||
auth = get_netrc_auth(request.url)
|
||||
|
||||
def prepare_request(self, request):
|
||||
req = request.copy()
|
||||
self.update_request(req)
|
||||
return req.prepare()
|
||||
p = PreparedRequest()
|
||||
p.prepare(
|
||||
method=request.method.upper(),
|
||||
url=request.url,
|
||||
files=request.files,
|
||||
data=request.data,
|
||||
headers=merge_setting(request.headers, self.headers, dict_class=CaseInsensitiveDict),
|
||||
params=merge_setting(request.params, self.params),
|
||||
auth=merge_setting(auth, self.auth),
|
||||
cookies=merged_cookies,
|
||||
hooks=merge_setting(request.hooks, self.hooks),
|
||||
)
|
||||
return p
|
||||
|
||||
def request(self, method, url,
|
||||
params=None,
|
||||
@@ -319,8 +323,7 @@ class Session(SessionRedirectMixin):
|
||||
cookies = cookies,
|
||||
hooks = hooks,
|
||||
)
|
||||
self.update_request(req)
|
||||
prep = req.prepare()
|
||||
prep = self.prepare_request(req)
|
||||
|
||||
proxies = proxies or {}
|
||||
|
||||
@@ -438,7 +441,7 @@ class Session(SessionRedirectMixin):
|
||||
|
||||
# It's possible that users might accidentally send a Request object.
|
||||
# Guard against that specific failure case.
|
||||
if getattr(request, 'prepare', None):
|
||||
if not isinstance(request, PreparedRequest):
|
||||
raise ValueError('You can only send PreparedRequests.')
|
||||
|
||||
# Set up variables needed for resolve_redirects and dispatching of
|
||||
|
||||
@@ -458,37 +458,6 @@ class RequestsTestCase(unittest.TestCase):
|
||||
|
||||
self.assertTrue(hasattr(resp, 'hook_working'))
|
||||
|
||||
def test_request_copy(self):
|
||||
a = requests.Request('POST', httpbin('post'),
|
||||
headers={'oh': 'gee'},
|
||||
files={'some': 'thing'},
|
||||
data={'baz':'qux'},
|
||||
params={'foo': 'bar'},
|
||||
auth=object(),
|
||||
cookies={'Some-Cookie':'Some Value'},
|
||||
hooks={'response': lambda r: r })
|
||||
b = a.copy()
|
||||
|
||||
self.assertNotEqual(a, b)
|
||||
self.assertEqual(a.method, b.method)
|
||||
self.assertEqual(a.url, b.url)
|
||||
self.assertEqual(a.headers, b.headers)
|
||||
self.assertEqual(a.files, b.files)
|
||||
self.assertEqual(a.data, b.data)
|
||||
self.assertEqual(a.params, b.params)
|
||||
self.assertEqual(a.auth, b.auth)
|
||||
self.assertEqual(a.cookies, b.cookies)
|
||||
self.assertEqual(a.hooks, b.hooks)
|
||||
|
||||
a.headers['Foo'] = 'Bar'
|
||||
self.assertNotEqual(a.headers, b.headers)
|
||||
|
||||
a.data['x'] = 'y'
|
||||
self.assertNotEqual(a.data, b.data)
|
||||
|
||||
a.params['_'] = '?'
|
||||
self.assertNotEqual(a.params, b.params)
|
||||
|
||||
def test_prepared_from_session(self):
|
||||
class DummyAuth(requests.auth.AuthBase):
|
||||
def __call__(self, r):
|
||||
|
||||
Reference in New Issue
Block a user