mirror of
https://github.com/kennethreitz/requests.git
synced 2026-06-05 22:50:18 +00:00
merge
This commit is contained in:
@@ -131,3 +131,4 @@ Patches and Suggestions
|
||||
- Dave Shawley <daveshawley@gmail.com>
|
||||
- James Clarke (jam)
|
||||
- Kevin Burke <kev@inburke.com>
|
||||
- Flavio Curella
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
Requests: HTTP for Humans
|
||||
=========================
|
||||
|
||||
.. image:: https://badge.fury.io/py/requests.png
|
||||
:target: http://badge.fury.io/py/requests
|
||||
|
||||
.. image:: https://travis-ci.org/kennethreitz/requests.png?branch=master
|
||||
:target: https://travis-ci.org/kennethreitz/requests
|
||||
|
||||
@@ -71,6 +71,9 @@ You can see that the URL has been correctly encoded by printing the URL::
|
||||
>>> print r.url
|
||||
http://httpbin.org/get?key2=value2&key1=value1
|
||||
|
||||
Note that any dictionary key whose value is ``None`` will not be added to the
|
||||
URL's query string.
|
||||
|
||||
|
||||
Response Content
|
||||
----------------
|
||||
|
||||
@@ -259,6 +259,11 @@ class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
|
||||
"""Deletes a cookie given a name. Wraps cookielib.CookieJar's remove_cookie_by_name()."""
|
||||
remove_cookie_by_name(self, name)
|
||||
|
||||
def set_cookie(self, cookie, *args, **kwargs):
|
||||
if cookie.value.startswith('"') and cookie.value.endswith('"'):
|
||||
cookie.value = cookie.value.replace('\\"', '')
|
||||
return super(RequestsCookieJar, self).set_cookie(cookie, *args, **kwargs)
|
||||
|
||||
def update(self, other):
|
||||
"""Updates this jar with cookies from another CookieJar or dict-like"""
|
||||
if isinstance(other, cookielib.CookieJar):
|
||||
|
||||
+1
-1
@@ -544,7 +544,7 @@ class Response(object):
|
||||
except AttributeError:
|
||||
# Standard file-like object.
|
||||
while 1:
|
||||
chunk = self.raw.read(chunk_size, decode_content=True)
|
||||
chunk = self.raw.read(chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
yield chunk
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
from collections import MutableMapping
|
||||
from threading import Lock
|
||||
from threading import RLock
|
||||
|
||||
try: # Python 2.7+
|
||||
from collections import OrderedDict
|
||||
@@ -40,18 +40,18 @@ class RecentlyUsedContainer(MutableMapping):
|
||||
self.dispose_func = dispose_func
|
||||
|
||||
self._container = self.ContainerCls()
|
||||
self._lock = Lock()
|
||||
self.lock = RLock()
|
||||
|
||||
def __getitem__(self, key):
|
||||
# Re-insert the item, moving it to the end of the eviction line.
|
||||
with self._lock:
|
||||
with self.lock:
|
||||
item = self._container.pop(key)
|
||||
self._container[key] = item
|
||||
return item
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
evicted_value = _Null
|
||||
with self._lock:
|
||||
with self.lock:
|
||||
# Possibly evict the existing value of 'key'
|
||||
evicted_value = self._container.get(key, _Null)
|
||||
self._container[key] = value
|
||||
@@ -65,21 +65,21 @@ class RecentlyUsedContainer(MutableMapping):
|
||||
self.dispose_func(evicted_value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
with self._lock:
|
||||
with self.lock:
|
||||
value = self._container.pop(key)
|
||||
|
||||
if self.dispose_func:
|
||||
self.dispose_func(value)
|
||||
|
||||
def __len__(self):
|
||||
with self._lock:
|
||||
with self.lock:
|
||||
return len(self._container)
|
||||
|
||||
def __iter__(self):
|
||||
raise NotImplementedError('Iteration over this class is unlikely to be threadsafe.')
|
||||
|
||||
def clear(self):
|
||||
with self._lock:
|
||||
with self.lock:
|
||||
# Copy pointers to all values, then wipe the mapping
|
||||
# under Python 2, this copies the list of values twice :-|
|
||||
values = list(self._container.values())
|
||||
@@ -90,5 +90,5 @@ class RecentlyUsedContainer(MutableMapping):
|
||||
self.dispose_func(value)
|
||||
|
||||
def keys(self):
|
||||
with self._lock:
|
||||
with self.lock:
|
||||
return self._container.keys()
|
||||
|
||||
@@ -106,6 +106,9 @@ class WrappedSocket(object):
|
||||
self.connection = connection
|
||||
self.socket = socket
|
||||
|
||||
def fileno(self):
|
||||
return self.socket.fileno()
|
||||
|
||||
def makefile(self, mode, bufsize=-1):
|
||||
return _fileobject(self.connection, mode, bufsize)
|
||||
|
||||
|
||||
@@ -104,15 +104,16 @@ class PoolManager(RequestMethods):
|
||||
|
||||
pool_key = (scheme, host, port)
|
||||
|
||||
# If the scheme, host, or port doesn't match existing open connections,
|
||||
# open a new ConnectionPool.
|
||||
pool = self.pools.get(pool_key)
|
||||
if pool:
|
||||
return pool
|
||||
with self.pools.lock:
|
||||
# If the scheme, host, or port doesn't match existing open connections,
|
||||
# open a new ConnectionPool.
|
||||
pool = self.pools.get(pool_key)
|
||||
if pool:
|
||||
return pool
|
||||
|
||||
# Make a fresh ConnectionPool of the desired type
|
||||
pool = self._new_pool(scheme, host, port)
|
||||
self.pools[pool_key] = pool
|
||||
# Make a fresh ConnectionPool of the desired type
|
||||
pool = self._new_pool(scheme, host, port)
|
||||
self.pools[pool_key] = pool
|
||||
return pool
|
||||
|
||||
def connection_from_url(self, url):
|
||||
|
||||
@@ -113,7 +113,7 @@ def parse_url(url):
|
||||
|
||||
# While this code has overlap with stdlib's urlparse, it is much
|
||||
# simplified for our needs and less annoying.
|
||||
# Additionally, this imeplementations does silly things to be optimal
|
||||
# Additionally, this implementations does silly things to be optimal
|
||||
# on CPython.
|
||||
|
||||
scheme = None
|
||||
@@ -142,7 +142,8 @@ def parse_url(url):
|
||||
|
||||
# IPv6
|
||||
if url and url[0] == '[':
|
||||
host, url = url[1:].split(']', 1)
|
||||
host, url = url.split(']', 1)
|
||||
host += ']'
|
||||
|
||||
# Port
|
||||
if ':' in url:
|
||||
|
||||
@@ -289,8 +289,8 @@ class Session(SessionRedirectMixin):
|
||||
for (k, v) in env_proxies.items():
|
||||
proxies.setdefault(k, v)
|
||||
|
||||
# Set environment's basic authentication.
|
||||
if not auth:
|
||||
# Set environment's basic authentication if not explicitly set.
|
||||
if not auth and not self.auth:
|
||||
auth = get_netrc_auth(url)
|
||||
|
||||
# Look for configuration.
|
||||
|
||||
@@ -18,7 +18,8 @@ _codes = {
|
||||
205: ('reset_content', 'reset'),
|
||||
206: ('partial_content', 'partial'),
|
||||
207: ('multi_status', 'multiple_status', 'multi_stati', 'multiple_stati'),
|
||||
208: ('im_used',),
|
||||
208: ('already_reported',),
|
||||
226: ('im_used',),
|
||||
|
||||
# Redirection.
|
||||
300: ('multiple_choices',),
|
||||
|
||||
@@ -170,6 +170,11 @@ class RequestsTestCase(unittest.TestCase):
|
||||
)
|
||||
assert 'foo' not in s.cookies
|
||||
|
||||
def test_cookie_quote_wrapped(self):
|
||||
s = requests.session()
|
||||
s.get(httpbin('cookies/set?foo="bar:baz"'))
|
||||
self.assertTrue(s.cookies['foo'] == '"bar:baz"')
|
||||
|
||||
def test_request_cookie_overrides_session_cookie(self):
|
||||
s = requests.session()
|
||||
s.cookies['foo'] = 'bar'
|
||||
@@ -234,6 +239,34 @@ class RequestsTestCase(unittest.TestCase):
|
||||
r = s.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_basicauth_with_netrc(self):
|
||||
auth = ('user', 'pass')
|
||||
wrong_auth = ('wronguser', 'wrongpass')
|
||||
url = httpbin('basic-auth', 'user', 'pass')
|
||||
|
||||
def get_netrc_auth_mock(url):
|
||||
return auth
|
||||
requests.sessions.get_netrc_auth = get_netrc_auth_mock
|
||||
|
||||
# Should use netrc and work.
|
||||
r = requests.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
# Given auth should override and fail.
|
||||
r = requests.get(url, auth=wrong_auth)
|
||||
self.assertEqual(r.status_code, 401)
|
||||
|
||||
s = requests.session()
|
||||
|
||||
# Should use netrc and work.
|
||||
r = s.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
# Given auth should override and fail.
|
||||
s.auth = wrong_auth
|
||||
r = s.get(url)
|
||||
self.assertEqual(r.status_code, 401)
|
||||
|
||||
def test_DIGEST_HTTP_200_OK_GET(self):
|
||||
|
||||
auth = HTTPDigestAuth('user', 'pass')
|
||||
|
||||
Reference in New Issue
Block a user