Skip to content

Commit

Permalink
merged upstream/master
Browse files Browse the repository at this point in the history
  • Loading branch information
mind1m committed Jul 24, 2016
2 parents d7f41bd + 4bf83a8 commit 944524e
Show file tree
Hide file tree
Showing 23 changed files with 173 additions and 58 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.swp
*.bak
*.egg
*.egg-info
Expand Down
26 changes: 25 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
CHANGES
=======

0.22.2 (XX-XX-XXXX)
0.23.0 (XX-XX-XXXX)
-------------------

- Change default size for client session's connection pool from
unlimited to 20 #977

- Add IE support for cookie deletion. #994

- Remove deprecated `WebSocketResponse.wait_closed` method (BACKWARD
INCOMPATIBLE)

- Remove deprecated `force` parameter for `ClientResponse.close`
method (BACKWARD INCOMPATIBLE)

- Avoid using of mutable CIMultiDict kw param in make_mocked_request
#997

0.22.2 (07-23-2016)
-------------------

- Suppress CancelledError when Timeout raises TimeoutError #970

- Don't expose `aiohttp.__version__`

- Add unsafe parameter to CookieJar #968

- Use unsafe cookie jar in test client tools

- Expose aiohttp.CookieJar name


0.22.1 (07-16-2016)
-------------------

Expand Down
7 changes: 7 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ After that please install libraries required for development::
We also recommend to install *ipdb* but it's on your own::

$ pip install ipdb
.. note::
If you plan to use ``ipdb`` within the test suite, use::
$ make vtest
to run the tests.

Congratulations, you are ready to run the test suite

Expand Down
3 changes: 3 additions & 0 deletions CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Contributors

A. Jesse Jiryu Davis
Alejandro Gómez
Aleksey Kutepov
Alex Khomchenko
Alex Lisovoy
Alex Key
Expand Down Expand Up @@ -65,6 +66,7 @@ Lubomir Gelo
Ludovic Gasc
Lukasz Marcin Dobrzanski
Marco Paolini
Mariano Anaya
Martin Richard
Mathias Fröjdman
Matthieu Hauglustaine
Expand Down Expand Up @@ -111,3 +113,4 @@ Yury Selivanov
Yusuke Tsutsumi
Марк Коренберг
Семён Марьясин
Pau Freixes
2 changes: 1 addition & 1 deletion aiohttp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This relies on each of the submodules having an __all__ variable.

__version__ = '0.22.2b0'
__version__ = '0.22.2'

import multidict # noqa

Expand Down
5 changes: 1 addition & 4 deletions aiohttp/client_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,10 +661,7 @@ def start(self, connection, read_until_eof=False):
'Can not load response cookies: %s', exc)
return self

def close(self, force=True):
if not force:
warnings.warn("force parameter should be True", DeprecationWarning,
stacklevel=2)
def close(self):
if self._closed:
return

Expand Down
12 changes: 10 additions & 2 deletions aiohttp/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,15 @@ class BaseConnector(object):
:param keepalive_timeout: (optional) Keep-alive timeout.
:param bool force_close: Set to True to force close and do reconnect
after each request (and between redirects).
:param limit: The limit of simultaneous connections to the same endpoint.
:param loop: Optional event loop.
"""

_closed = True # prevent AttributeError in __del__ if ctor was failed
_source_traceback = None

def __init__(self, *, conn_timeout=None, keepalive_timeout=_default,
force_close=False, limit=None,
force_close=False, limit=20,
loop=None):

if force_close:
Expand Down Expand Up @@ -170,6 +171,12 @@ def __del__(self, _warnings=warnings):
context['source_traceback'] = self._source_traceback
self._loop.call_exception_handler(context)

def __enter__(self):
return self

def __exit__(self, *exc):
self.close()

@property
def force_close(self):
"""Ultimately close connection on releasing if True."""
Expand All @@ -182,7 +189,8 @@ def limit(self):
Endpoints are the same if they are have equal
(host, port, is_ssl) triple.
If limit is None the connector has no limit (default).
If limit is None the connector has no limit.
The default limit size is 20.
"""
return self._limit

Expand Down
7 changes: 4 additions & 3 deletions aiohttp/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@


__all__ = ('BasicAuth', 'create_future', 'FormData', 'parse_mimetype',
'Timeout')
'Timeout', 'CookieJar')


class BasicAuth(namedtuple('BasicAuth', ['login', 'password', 'encoding'])):
Expand Down Expand Up @@ -587,9 +587,10 @@ class CookieJar(AbstractCookieJar):

DATE_YEAR_RE = re.compile("(\d{2,4})")

def __init__(self, *, loop=None):
def __init__(self, *, unsafe=False, loop=None):
super().__init__(loop=loop)
self._host_only_cookies = set()
self._unsafe = unsafe

def _expire_cookie(self, when, name, DAY=24*3600):
now = self._loop.time()
Expand All @@ -608,7 +609,7 @@ def update_cookies(self, cookies, response_url=None):
url_parsed = urlsplit(response_url or "")
hostname = url_parsed.hostname

if is_ip_address(hostname):
if not self._unsafe and is_ip_address(hostname):
# Don't accept cookies from IPs
return

Expand Down
22 changes: 16 additions & 6 deletions aiohttp/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,10 @@ def __init__(self, app, protocol="http"):
self._server = None
if not loop.is_running():
loop.run_until_complete(self.start_server())
self._session = ClientSession(loop=self._loop)
self._session = ClientSession(
loop=self._loop,
cookie_jar=aiohttp.CookieJar(unsafe=True,
loop=self._loop))
self._root = '{}://{}:{}'.format(protocol, self._address, self.port)
self._closed = False

Expand Down Expand Up @@ -558,7 +561,7 @@ def get_extra_info(key):
_not_set = object()


def make_mocked_request(method, path, headers=CIMultiDict(), *,
def make_mocked_request(method, path, headers=None, *,
version=HttpVersion(1, 1), closing=False,
app=None,
reader=_not_set,
Expand Down Expand Up @@ -613,10 +616,17 @@ def make_mocked_request(method, path, headers=CIMultiDict(), *,

if version < HttpVersion(1, 1):
closing = True
message = RawRequestMessage(method, path, version, headers,
[(k.encode('utf-8'), v.encode('utf-8'))
for k, v in headers.items()],
closing, False)

if headers:
hdrs = headers
raw_hdrs = [
(k.encode('utf-8'), v.encode('utf-8')) for k, v in headers.items()]
else:
hdrs = CIMultiDict()
raw_hdrs = []

message = RawRequestMessage(method, path, version, hdrs,
raw_hdrs, closing, False)
if app is None:
app = _create_app_mock()

Expand Down
8 changes: 7 additions & 1 deletion aiohttp/web_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,8 +511,12 @@ def set_cookie(self, name, value, *, expires=None,

self._cookies[name] = value
c = self._cookies[name]

if expires is not None:
c['expires'] = expires
elif c.get('expires') == 'Thu, 01 Jan 1970 00:00:00 GMT':
del c['expires']

if domain is not None:
c['domain'] = domain

Expand All @@ -537,7 +541,9 @@ def del_cookie(self, name, *, domain=None, path='/'):
"""
# TODO: do we need domain/path here?
self._cookies.pop(name, None)
self.set_cookie(name, '', max_age=0, domain=domain, path=path)
self.set_cookie(name, '', max_age=0,
expires="Thu, 01 Jan 1970 00:00:00 GMT",
domain=domain, path=path)

@property
def content_length(self):
Expand Down
8 changes: 0 additions & 8 deletions aiohttp/web_ws.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,6 @@ def send_bytes(self, data):
type(data))
self._writer.send(data, binary=True)

@asyncio.coroutine
def wait_closed(self): # pragma: no cover
warnings.warn(
'wait_closed() coroutine is deprecated. use close() instead',
DeprecationWarning)

return (yield from self.close())

@asyncio.coroutine
def write_eof(self):
if self._eof_sent:
Expand Down
25 changes: 25 additions & 0 deletions docs/client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,24 @@ You also can set default headers for all session requests::
:class:`~aiohttp.ClientSession` supports keep-alive requests
and connection pooling out-of-the-box.

.. _aiohttp-client-cookie-safety:

Cookie safety
-------------

By default :class:`~aiohttp.ClientSession` uses strict version of
:class:`~aiohttp.CookieJar`. :rfc:`2109` explicitly forbids cookie
accepting from URLs with IP address instead of DNS name
(e.g. `http://127.0.0.1:80/cookie`).

It's good but sometimes for testing we need to enable support for such
cookies. It should be done by passing `usafe=True` to
:class:`~aiohttp.CookieJar` constructor::


jar = aiohttp.CookieJar(unsafe=True)
session = aiohttp.ClientSession(cookie_jar=jar)


Connectors
----------
Expand Down Expand Up @@ -413,6 +431,13 @@ parameter to *connector*::

The example limits amount of parallel connections to `30`.

The default is `20`.

If you explicitly want not to have limits to the same endpoint,
pass `None`. For example::

conn = aiohttp.TCPConnector(limit=None)


Resolving using custom nameservers
----------------------------------
Expand Down
9 changes: 8 additions & 1 deletion docs/client_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ BaseConnector
^^^^^^^^^^^^^

.. class:: BaseConnector(*, conn_timeout=None, keepalive_timeout=30, \
limit=None, \
limit=20, \
force_close=False, loop=None)

Base class for all connectors.
Expand Down Expand Up @@ -730,6 +730,13 @@ BaseConnector
recommend to use explicit loops everywhere.
(optional)

.. versionchanged:: 0.23

``limit`` changed from unlimited (``None``) to 20.
Expect a max of up to 20 connections to the same endpoint,
if it is not especified.
For limitless connections, pass `None` explicitly.

.. attribute:: closed

Read-only property, ``True`` if connector is closed.
Expand Down
21 changes: 17 additions & 4 deletions docs/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,11 @@ functionality, the AioHTTPTestCase is provided::
Faking request object
---------------------

aiohttp provides test utility for creating fake `web.Request` objects:
:data:`aiohttp.test_utils.make_mocked_request`, it could be useful in case of
simple unit tests, like handler tests, or simulate error conditions that
hard to reproduce on real server. ::
aiohttp provides test utility for creating fake
:class:`aiohttp.web.Request` objects:
:func:`aiohttp.test_utils.make_mocked_request`, it could be useful in
case of simple unit tests, like handler tests, or simulate error
conditions that hard to reproduce on real server::

from aiohttp import web

Expand All @@ -201,6 +202,18 @@ hard to reproduce on real server. ::
resp = header(req)
assert resp.body == b'data'

.. warning::

We don't recommed to apply
:func:`~aiohttp.test_utils.make_mocked_request` everywhere for
testing web-handler's business object -- please use test client and
real networking via 'localhost' as shown in examples before.

:func:`~aiohttp.test_utils.make_mocked_request` exists only for
testing complex cases (e.g. emulating network errors) which
are extremely hard or even impossible to test by conventional
way.


aiohttp.test_utils
------------------
Expand Down
5 changes: 5 additions & 0 deletions docs/web_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,11 @@ StreamResponse

:param str path: optional cookie path, ``'/'`` by default

.. versionchanged:: 0.23

Fixed cookie expiration support for
Internet Explorer (version less than 11).

.. attribute:: content_length

*Content-Length* for outgoing response.
Expand Down
2 changes: 1 addition & 1 deletion examples/basic_srv.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import asyncio
from urllib.parse import urlparse, parse_qsl
from aiohttp.multidict import MultiDict
from aiohttp import MultiDict


class HttpRequestHandler(aiohttp.server.ServerHttpProtocol):
Expand Down
6 changes: 0 additions & 6 deletions tests/test_client_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,6 @@ def test_get_encoding_unknown(self, m_chardet):
self.response.headers = {'CONTENT-TYPE': 'application/json'}
self.assertEqual(self.response._get_encoding(), 'utf-8')

def test_close_deprecated(self):
self.response._connection = self.connection
with self.assertWarns(DeprecationWarning):
self.response.close(force=False)
self.assertIsNone(self.response._connection)

def test_raise_for_status_2xx(self):
self.response.status = 200
self.response.reason = 'OK'
Expand Down
6 changes: 5 additions & 1 deletion tests/test_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,9 +682,13 @@ def test_limit_property(self):

def test_limit_property_default(self):
conn = aiohttp.BaseConnector(loop=self.loop)
self.assertIsNone(conn.limit)
self.assertEquals(conn.limit, 20)
conn.close()

def test_limitless(self):
with aiohttp.BaseConnector(loop=self.loop, limit=None) as conn:
self.assertIsNone(conn.limit)

def test_force_close_and_explicit_keep_alive(self):
with self.assertRaises(ValueError):
aiohttp.BaseConnector(loop=self.loop, keepalive_timeout=30,
Expand Down
Loading

0 comments on commit 944524e

Please sign in to comment.