From 73f38a23473dbe1958e85228e6adfd1050239f66 Mon Sep 17 00:00:00 2001 From: sgoudham Date: Sun, 7 Jun 2020 04:38:24 +0100 Subject: [PATCH] Added more requirements --- cogs/WaifuImages.py | 2 +- .../aiohttp-1.0.5-py3.6.egg-info/PKG-INFO | 354 + .../aiohttp-1.0.5-py3.6.egg-info/SOURCES.txt | 162 + .../dependency_links.txt | 1 + .../installed-files.txt | 65 + .../aiohttp-1.0.5-py3.6.egg-info/requires.txt | 3 + .../top_level.txt | 0 .../aiohttp-3.6.2.dist-info/LICENSE.txt | 201 - .../aiohttp-3.6.2.dist-info/METADATA | 652 - .../aiohttp-3.6.2.dist-info/RECORD | 124 - .../aiohttp-3.6.2.dist-info/WHEEL | 5 - venv/Lib/site-packages/aiohttp/__init__.py | 259 +- venv/Lib/site-packages/aiohttp/_cparser.pxd | 140 - venv/Lib/site-packages/aiohttp/_find_header.c | 10000 ---------------- venv/Lib/site-packages/aiohttp/_find_header.h | 14 - .../site-packages/aiohttp/_find_header.pxd | 2 - venv/Lib/site-packages/aiohttp/_frozenlist.c | 7355 ------------ venv/Lib/site-packages/aiohttp/_websocket.c | 2100 +--- venv/Lib/site-packages/aiohttp/_websocket.pyx | 14 +- venv/Lib/site-packages/aiohttp/_ws_impl.py | 438 + venv/Lib/site-packages/aiohttp/abc.py | 186 +- .../site-packages/aiohttp/base_protocol.py | 81 - venv/Lib/site-packages/aiohttp/client.py | 1301 +- .../aiohttp/client_exceptions.py | 292 - .../Lib/site-packages/aiohttp/client_proto.py | 239 - .../site-packages/aiohttp/client_reqrep.py | 1259 +- venv/Lib/site-packages/aiohttp/client_ws.py | 298 +- venv/Lib/site-packages/aiohttp/connector.py | 1344 +-- venv/Lib/site-packages/aiohttp/cookiejar.py | 176 +- venv/Lib/site-packages/aiohttp/errors.py | 186 + venv/Lib/site-packages/aiohttp/formdata.py | 150 - venv/Lib/site-packages/aiohttp/frozenlist.py | 72 - venv/Lib/site-packages/aiohttp/frozenlist.pyi | 63 - venv/Lib/site-packages/aiohttp/hdrs.py | 151 +- venv/Lib/site-packages/aiohttp/helpers.py | 1005 +- venv/Lib/site-packages/aiohttp/http.py | 50 - .../site-packages/aiohttp/http_exceptions.py | 108 - venv/Lib/site-packages/aiohttp/http_parser.py | 764 -- .../site-packages/aiohttp/http_websocket.py | 659 - venv/Lib/site-packages/aiohttp/http_writer.py | 172 - venv/Lib/site-packages/aiohttp/locks.py | 44 - venv/Lib/site-packages/aiohttp/multipart.py | 1096 +- venv/Lib/site-packages/aiohttp/parsers.py | 495 + venv/Lib/site-packages/aiohttp/payload.py | 456 - .../site-packages/aiohttp/payload_streamer.py | 74 - venv/Lib/site-packages/aiohttp/protocol.py | 916 ++ venv/Lib/site-packages/aiohttp/py.typed | 1 - .../site-packages/aiohttp/pytest_plugin.py | 329 +- venv/Lib/site-packages/aiohttp/resolver.py | 68 +- venv/Lib/site-packages/aiohttp/server.py | 376 + venv/Lib/site-packages/aiohttp/signals.py | 73 +- venv/Lib/site-packages/aiohttp/signals.pyi | 17 - venv/Lib/site-packages/aiohttp/streams.py | 654 +- venv/Lib/site-packages/aiohttp/tcp_helpers.py | 63 - venv/Lib/site-packages/aiohttp/test_utils.py | 653 +- venv/Lib/site-packages/aiohttp/tracing.py | 387 - venv/Lib/site-packages/aiohttp/typedefs.py | 53 - venv/Lib/site-packages/aiohttp/web.py | 766 +- venv/Lib/site-packages/aiohttp/web_app.py | 514 - .../site-packages/aiohttp/web_exceptions.py | 88 +- .../site-packages/aiohttp/web_fileresponse.py | 346 - venv/Lib/site-packages/aiohttp/web_log.py | 235 - .../site-packages/aiohttp/web_middlewares.py | 120 - .../Lib/site-packages/aiohttp/web_protocol.py | 599 - venv/Lib/site-packages/aiohttp/web_reqrep.py | 895 ++ venv/Lib/site-packages/aiohttp/web_request.py | 754 -- .../Lib/site-packages/aiohttp/web_response.py | 717 -- .../Lib/site-packages/aiohttp/web_routedef.py | 194 - venv/Lib/site-packages/aiohttp/web_runner.py | 337 - venv/Lib/site-packages/aiohttp/web_server.py | 57 - .../aiohttp/web_urldispatcher.py | 1112 +- venv/Lib/site-packages/aiohttp/web_ws.py | 552 +- venv/Lib/site-packages/aiohttp/worker.py | 183 +- venv/Lib/site-packages/aiohttp/wsgi.py | 235 + .../site-packages/discord/ext/commands/bot.py | 1 - .../websockets-3.4.dist-info/DESCRIPTION.rst | 30 + .../INSTALLER | 0 .../websockets-3.4.dist-info/METADATA | 52 + .../websockets-3.4.dist-info/RECORD | 56 + .../WHEEL | 2 +- .../websockets-3.4.dist-info/metadata.json | 1 + .../websockets-3.4.dist-info/top_level.txt | 2 + .../websockets-8.1.dist-info/INSTALLER | 1 - .../websockets-8.1.dist-info/LICENSE | 25 - .../websockets-8.1.dist-info/METADATA | 167 - .../websockets-8.1.dist-info/RECORD | 44 - .../websockets-8.1.dist-info/top_level.txt | 2 - venv/Lib/site-packages/websockets/__init__.py | 64 +- venv/Lib/site-packages/websockets/auth.py | 160 - venv/Lib/site-packages/websockets/client.py | 651 +- .../site-packages/websockets/compatibility.py | 48 + .../site-packages/websockets/exceptions.py | 343 +- .../websockets/extensions/base.py | 119 - .../extensions/permessage_deflate.py | 588 - venv/Lib/site-packages/websockets/framing.py | 428 +- .../Lib/site-packages/websockets/handshake.py | 185 +- venv/Lib/site-packages/websockets/headers.py | 515 - venv/Lib/site-packages/websockets/http.py | 358 +- venv/Lib/site-packages/websockets/protocol.py | 1594 +-- venv/Lib/site-packages/websockets/py.typed | 0 .../site-packages/websockets/py35/__init__.py | 2 + .../site-packages/websockets/py35/client.py | 21 + .../websockets/py35/client_server.py | 43 + .../site-packages/websockets/py35/server.py | 22 + venv/Lib/site-packages/websockets/server.py | 1107 +- .../websockets/speedups.cp36-win_amd64.pyd | Bin 12288 -> 11264 bytes .../websockets/test_client_server.py | 622 + .../site-packages/websockets/test_framing.py | 146 + .../websockets/test_handshake.py | 117 + .../Lib/site-packages/websockets/test_http.py | 128 + .../site-packages/websockets/test_protocol.py | 789 ++ .../__init__.py => test_speedups.py} | 0 venv/Lib/site-packages/websockets/test_uri.py | 33 + .../site-packages/websockets/test_utils.py | 50 + venv/Lib/site-packages/websockets/uri.py | 90 +- venv/Lib/site-packages/websockets/utils.py | 10 +- venv/Lib/site-packages/websockets/version.py | 2 +- venv/Lib/site-packages/~ebsockets/__init__.py | 55 + .../{websockets => ~ebsockets}/__main__.py | 0 .../~ebsockets/speedups.cp36-win_amd64.pyd | Bin 0 -> 12288 bytes .../{websockets => ~ebsockets}/typing.py | 0 venv/Lib/site-packages/~ebsockets/uri.py | 81 + venv/Lib/site-packages/~ebsockets/utils.py | 18 + venv/Lib/site-packages/~ebsockets/version.py | 1 + venv/Lib/site-packages/~iohttp/__init__.py | 226 + .../_frozenlist.cp36-win_amd64.pyd | Bin .../{aiohttp => ~iohttp}/_frozenlist.pyx | 0 .../{aiohttp => ~iohttp}/_headers.pxi | 0 .../{aiohttp => ~iohttp}/_helpers.c | 0 .../_helpers.cp36-win_amd64.pyd | Bin .../{aiohttp => ~iohttp}/_helpers.pyi | 0 .../{aiohttp => ~iohttp}/_helpers.pyx | 0 .../{aiohttp => ~iohttp}/_http_parser.c | 0 .../_http_parser.cp36-win_amd64.pyd | Bin .../{aiohttp => ~iohttp}/_http_parser.pyx | 0 .../{aiohttp => ~iohttp}/_http_writer.c | 0 .../_http_writer.cp36-win_amd64.pyd | Bin .../{aiohttp => ~iohttp}/_http_writer.pyx | 0 venv/Lib/site-packages/~iohttp/_websocket.c | 3562 ++++++ .../_websocket.cp36-win_amd64.pyd | Bin venv/Lib/site-packages/~iohttp/_websocket.pyx | 54 + 141 files changed, 16485 insertions(+), 40036 deletions(-) create mode 100644 venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/PKG-INFO create mode 100644 venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/SOURCES.txt create mode 100644 venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/dependency_links.txt create mode 100644 venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/installed-files.txt create mode 100644 venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/requires.txt rename venv/Lib/site-packages/{aiohttp-3.6.2.dist-info => aiohttp-1.0.5-py3.6.egg-info}/top_level.txt (100%) delete mode 100644 venv/Lib/site-packages/aiohttp-3.6.2.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/aiohttp-3.6.2.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/aiohttp-3.6.2.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/aiohttp-3.6.2.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/aiohttp/_cparser.pxd delete mode 100644 venv/Lib/site-packages/aiohttp/_find_header.c delete mode 100644 venv/Lib/site-packages/aiohttp/_find_header.h delete mode 100644 venv/Lib/site-packages/aiohttp/_find_header.pxd delete mode 100644 venv/Lib/site-packages/aiohttp/_frozenlist.c create mode 100644 venv/Lib/site-packages/aiohttp/_ws_impl.py delete mode 100644 venv/Lib/site-packages/aiohttp/base_protocol.py delete mode 100644 venv/Lib/site-packages/aiohttp/client_exceptions.py delete mode 100644 venv/Lib/site-packages/aiohttp/client_proto.py create mode 100644 venv/Lib/site-packages/aiohttp/errors.py delete mode 100644 venv/Lib/site-packages/aiohttp/formdata.py delete mode 100644 venv/Lib/site-packages/aiohttp/frozenlist.py delete mode 100644 venv/Lib/site-packages/aiohttp/frozenlist.pyi delete mode 100644 venv/Lib/site-packages/aiohttp/http.py delete mode 100644 venv/Lib/site-packages/aiohttp/http_exceptions.py delete mode 100644 venv/Lib/site-packages/aiohttp/http_parser.py delete mode 100644 venv/Lib/site-packages/aiohttp/http_websocket.py delete mode 100644 venv/Lib/site-packages/aiohttp/http_writer.py delete mode 100644 venv/Lib/site-packages/aiohttp/locks.py create mode 100644 venv/Lib/site-packages/aiohttp/parsers.py delete mode 100644 venv/Lib/site-packages/aiohttp/payload.py delete mode 100644 venv/Lib/site-packages/aiohttp/payload_streamer.py create mode 100644 venv/Lib/site-packages/aiohttp/protocol.py delete mode 100644 venv/Lib/site-packages/aiohttp/py.typed create mode 100644 venv/Lib/site-packages/aiohttp/server.py delete mode 100644 venv/Lib/site-packages/aiohttp/signals.pyi delete mode 100644 venv/Lib/site-packages/aiohttp/tcp_helpers.py delete mode 100644 venv/Lib/site-packages/aiohttp/tracing.py delete mode 100644 venv/Lib/site-packages/aiohttp/typedefs.py delete mode 100644 venv/Lib/site-packages/aiohttp/web_app.py delete mode 100644 venv/Lib/site-packages/aiohttp/web_fileresponse.py delete mode 100644 venv/Lib/site-packages/aiohttp/web_log.py delete mode 100644 venv/Lib/site-packages/aiohttp/web_middlewares.py delete mode 100644 venv/Lib/site-packages/aiohttp/web_protocol.py create mode 100644 venv/Lib/site-packages/aiohttp/web_reqrep.py delete mode 100644 venv/Lib/site-packages/aiohttp/web_request.py delete mode 100644 venv/Lib/site-packages/aiohttp/web_response.py delete mode 100644 venv/Lib/site-packages/aiohttp/web_routedef.py delete mode 100644 venv/Lib/site-packages/aiohttp/web_runner.py delete mode 100644 venv/Lib/site-packages/aiohttp/web_server.py create mode 100644 venv/Lib/site-packages/aiohttp/wsgi.py create mode 100644 venv/Lib/site-packages/websockets-3.4.dist-info/DESCRIPTION.rst rename venv/Lib/site-packages/{aiohttp-3.6.2.dist-info => websockets-3.4.dist-info}/INSTALLER (100%) create mode 100644 venv/Lib/site-packages/websockets-3.4.dist-info/METADATA create mode 100644 venv/Lib/site-packages/websockets-3.4.dist-info/RECORD rename venv/Lib/site-packages/{websockets-8.1.dist-info => websockets-3.4.dist-info}/WHEEL (68%) create mode 100644 venv/Lib/site-packages/websockets-3.4.dist-info/metadata.json create mode 100644 venv/Lib/site-packages/websockets-3.4.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/websockets-8.1.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/websockets-8.1.dist-info/LICENSE delete mode 100644 venv/Lib/site-packages/websockets-8.1.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/websockets-8.1.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/websockets-8.1.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/websockets/auth.py create mode 100644 venv/Lib/site-packages/websockets/compatibility.py delete mode 100644 venv/Lib/site-packages/websockets/extensions/base.py delete mode 100644 venv/Lib/site-packages/websockets/extensions/permessage_deflate.py delete mode 100644 venv/Lib/site-packages/websockets/headers.py delete mode 100644 venv/Lib/site-packages/websockets/py.typed create mode 100644 venv/Lib/site-packages/websockets/py35/__init__.py create mode 100644 venv/Lib/site-packages/websockets/py35/client.py create mode 100644 venv/Lib/site-packages/websockets/py35/client_server.py create mode 100644 venv/Lib/site-packages/websockets/py35/server.py create mode 100644 venv/Lib/site-packages/websockets/test_client_server.py create mode 100644 venv/Lib/site-packages/websockets/test_framing.py create mode 100644 venv/Lib/site-packages/websockets/test_handshake.py create mode 100644 venv/Lib/site-packages/websockets/test_http.py create mode 100644 venv/Lib/site-packages/websockets/test_protocol.py rename venv/Lib/site-packages/websockets/{extensions/__init__.py => test_speedups.py} (100%) create mode 100644 venv/Lib/site-packages/websockets/test_uri.py create mode 100644 venv/Lib/site-packages/websockets/test_utils.py create mode 100644 venv/Lib/site-packages/~ebsockets/__init__.py rename venv/Lib/site-packages/{websockets => ~ebsockets}/__main__.py (100%) create mode 100644 venv/Lib/site-packages/~ebsockets/speedups.cp36-win_amd64.pyd rename venv/Lib/site-packages/{websockets => ~ebsockets}/typing.py (100%) create mode 100644 venv/Lib/site-packages/~ebsockets/uri.py create mode 100644 venv/Lib/site-packages/~ebsockets/utils.py create mode 100644 venv/Lib/site-packages/~ebsockets/version.py create mode 100644 venv/Lib/site-packages/~iohttp/__init__.py rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_frozenlist.cp36-win_amd64.pyd (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_frozenlist.pyx (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_headers.pxi (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_helpers.c (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_helpers.cp36-win_amd64.pyd (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_helpers.pyi (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_helpers.pyx (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_http_parser.c (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_http_parser.cp36-win_amd64.pyd (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_http_parser.pyx (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_http_writer.c (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_http_writer.cp36-win_amd64.pyd (100%) rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_http_writer.pyx (100%) create mode 100644 venv/Lib/site-packages/~iohttp/_websocket.c rename venv/Lib/site-packages/{aiohttp => ~iohttp}/_websocket.cp36-win_amd64.pyd (100%) create mode 100644 venv/Lib/site-packages/~iohttp/_websocket.pyx diff --git a/cogs/WaifuImages.py b/cogs/WaifuImages.py index 41bf5bbe..5fcdefa5 100644 --- a/cogs/WaifuImages.py +++ b/cogs/WaifuImages.py @@ -58,7 +58,7 @@ class Waifus(commands.Cog): async def toga(self, ctx): try: - # path = PureWindowsPath(r'C:\Users\sgoud\PycharmProjects\EnsoBot\images\togaImages.txt') + with open('images/togaImages.txt') as file: toga_array = file.readlines() diff --git a/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/PKG-INFO b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/PKG-INFO new file mode 100644 index 00000000..5b48099a --- /dev/null +++ b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/PKG-INFO @@ -0,0 +1,354 @@ +Metadata-Version: 1.2 +Name: aiohttp +Version: 1.0.5 +Summary: http client/server for asyncio +Home-page: https://github.com/KeepSafe/aiohttp/ +Author: Nikolay Kim +Author-email: fafhrd91@gmail.com +Maintainer: Andrew Svetlov +Maintainer-email: andrew.svetlov@gmail.com +License: Apache 2 +Description: http client/server for asyncio + ============================== + + .. image:: https://raw.github.com/KeepSafe/aiohttp/master/docs/_static/aiohttp-icon-128x128.png + :height: 64px + :width: 64px + :alt: aiohttp logo + + .. image:: https://travis-ci.org/KeepSafe/aiohttp.svg?branch=master + :target: https://travis-ci.org/KeepSafe/aiohttp + :align: right + + .. image:: https://codecov.io/gh/KeepSafe/aiohttp/branch/master/graph/badge.svg + :target: https://codecov.io/gh/KeepSafe/aiohttp + + .. image:: https://badge.fury.io/py/aiohttp.svg + :target: https://badge.fury.io/py/aiohttp + + Features + -------- + + - Supports both client and server side of HTTP protocol. + - Supports both client and server Web-Sockets out-of-the-box. + - Web-server has middlewares and pluggable routing. + + + Getting started + --------------- + + Client + ^^^^^^ + + To retrieve something from the web: + + .. code-block:: python + + import aiohttp + import asyncio + + async def fetch(session, url): + with aiohttp.Timeout(10, loop=session.loop): + async with session.get(url) as response: + return await response.text() + + async def main(loop): + async with aiohttp.ClientSession(loop=loop) as session: + html = await fetch(session, 'http://python.org') + print(html) + + if __name__ == '__main__': + loop = asyncio.get_event_loop() + loop.run_until_complete(main(loop)) + + + Server + ^^^^^^ + + This is simple usage example: + + .. code-block:: python + + from aiohttp import web + + async def handle(request): + name = request.match_info.get('name', "Anonymous") + text = "Hello, " + name + return web.Response(text=text) + + async def wshandler(request): + ws = web.WebSocketResponse() + await ws.prepare(request) + + async for msg in ws: + if msg.type == web.MsgType.text: + ws.send_str("Hello, {}".format(msg.data)) + elif msg.type == web.MsgType.binary: + ws.send_bytes(msg.data) + elif msg.type == web.MsgType.close: + break + + return ws + + + app = web.Application() + app.router.add_get('/echo', wshandler) + app.router.add_get('/', handle) + app.router.add_get('/{name}', handle) + + web.run_app(app) + + + Note: examples are written for Python 3.5+ and utilize PEP-492 aka + async/await. If you are using Python 3.4 please replace ``await`` with + ``yield from`` and ``async def`` with ``@coroutine`` e.g.:: + + async def coro(...): + ret = await f() + + should be replaced by:: + + @asyncio.coroutine + def coro(...): + ret = yield from f() + + Documentation + ------------- + + https://aiohttp.readthedocs.io/ + + Discussion list + --------------- + + *aio-libs* google group: https://groups.google.com/forum/#!forum/aio-libs + + Requirements + ------------ + + - Python >= 3.4.2 + - chardet_ + - multidict_ + + Optionally you may install the cChardet_ and aiodns_ libraries (highly + recommended for sake of speed). + + .. _chardet: https://pypi.python.org/pypi/chardet + .. _aiodns: https://pypi.python.org/pypi/aiodns + .. _multidict: https://pypi.python.org/pypi/multidict + .. _cChardet: https://pypi.python.org/pypi/cchardet + + License + ------- + + ``aiohttp`` is offered under the Apache 2 license. + + + Source code + ------------ + + The latest developer version is available in a github repository: + https://github.com/KeepSafe/aiohttp + + Benchmarks + ---------- + + If you are interested in by efficiency, AsyncIO community maintains a + list of benchmarks on the official wiki: + https://github.com/python/asyncio/wiki/Benchmarks + + CHANGES + ======= + + 1.0.5 (2016-10-11) + ------------------ + + - Fix StreamReader._read_nowait to return all available + data up to the requested amount #1297 + + + 1.0.4 (2016-09-22) + ------------------ + + - Fix FlowControlStreamReader.read_nowait so that it checks + whether the transport is paused #1206 + + + 1.0.2 (2016-09-22) + ------------------ + + - Make CookieJar compatible with 32-bit systems #1188 + + - Add missing `WSMsgType` to `web_ws.__all__`, see #1200 + + - Fix `CookieJar` ctor when called with `loop=None` #1203 + + - Fix broken upper-casing in wsgi support #1197 + + + 1.0.1 (2016-09-16) + ------------------ + + - Restore `aiohttp.web.MsgType` alias for `aiohttp.WSMsgType` for sake + of backward compatibility #1178 + + - Tune alabaster schema. + + - Use `text/html` content type for displaying index pages by static + file handler. + + - Fix `AssertionError` in static file handling #1177 + + - Fix access log formats `%O` and `%b` for static file handling + + - Remove `debug` setting of GunicornWorker, use `app.debug` + to control its debug-mode instead + + + 1.0.0 (2016-09-16) + ------------------- + + - 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 + + - Make WebSocketResponse.close a little bit faster by avoiding new + task creating just for timeout measurement + + - Add `proxy` and `proxy_auth` params to `client.get()` and family, + deprecate `ProxyConnector` #998 + + - Add support for websocket send_json and receive_json, synchronize + server and client API for websockets #984 + + - Implement router shourtcuts for most useful HTTP methods, use + `app.router.add_get()`, `app.router.add_post()` etc. instead of + `app.router.add_route()` #986 + + - Support SSL connections for gunicorn worker #1003 + + - Move obsolete examples to legacy folder + + - Switch to multidict 2.0 and title-cased strings #1015 + + - `{FOO}e` logger format is case-sensitive now + + - Fix logger report for unix socket 8e8469b + + - Rename aiohttp.websocket to aiohttp._ws_impl + + - Rename aiohttp.MsgType tp aiohttp.WSMsgType + + - Introduce aiohttp.WSMessage officially + + - Rename Message -> WSMessage + + - Remove deprecated decode param from resp.read(decode=True) + + - Use 5min default client timeout #1028 + + - Relax HTTP method validation in UrlDispatcher #1037 + + - Pin minimal supported asyncio version to 3.4.2+ (`loop.is_close()` + should be present) + + - Remove aiohttp.websocket module (BACKWARD INCOMPATIBLE) + Please use high-level client and server approaches + + - Link header for 451 status code is mandatory + + - Fix test_client fixture to allow multiple clients per test #1072 + + - make_mocked_request now accepts dict as headers #1073 + + - Add Python 3.5.2/3.6+ compatibility patch for async generator + protocol change #1082 + + - Improvement test_client can accept instance object #1083 + + - Simplify ServerHttpProtocol implementation #1060 + + - Add a flag for optional showing directory index for static file + handling #921 + + - Define `web.Application.on_startup()` signal handler #1103 + + - Drop ChunkedParser and LinesParser #1111 + + - Call `Application.startup` in GunicornWebWorker #1105 + + - Fix client handling hostnames with 63 bytes when a port is given in + the url #1044 + + - Implement proxy support for ClientSession.ws_connect #1025 + + - Return named tuple from WebSocketResponse.can_prepare #1016 + + - Fix access_log_format in `GunicornWebWorker` #1117 + + - Setup Content-Type to application/octet-stream by default #1124 + + - Deprecate debug parameter from app.make_handler(), use + `Application(debug=True)` instead #1121 + + - Remove fragment string in request path #846 + + - Use aiodns.DNSResolver.gethostbyname() if available #1136 + + - Fix static file sending on uvloop when sendfile is available #1093 + + - Make prettier urls if query is empty dict #1143 + + - Fix redirects for HEAD requests #1147 + + - Default value for `StreamReader.read_nowait` is -1 from now #1150 + + - `aiohttp.StreamReader` is not inherited from `asyncio.StreamReader` from now + (BACKWARD INCOMPATIBLE) #1150 + + - Streams documentation added #1150 + + - Add `multipart` coroutine method for web Request object #1067 + + - Publish ClientSession.loop property #1149 + + - Fix static file with spaces #1140 + + - Fix piling up asyncio loop by cookie expiration callbacks #1061 + + - Drop `Timeout` class for sake of `async_timeout` external library. + `aiohttp.Timeout` is an alias for `async_timeout.timeout` + + - `use_dns_cache` parameter of `aiohttp.TCPConnector` is `True` by + default (BACKWARD INCOMPATIBLE) #1152 + + - `aiohttp.TCPConnector` uses asynchronous DNS resolver if available by + default (BACKWARD INCOMPATIBLE) #1152 + + - Conform to RFC3986 - do not include url fragments in client requests #1174 + + - Drop `ClientSession.cookies` (BACKWARD INCOMPATIBLE) #1173 + + - Refactor `AbstractCookieJar` public API (BACKWARD INCOMPATIBLE) #1173 + + - Fix clashing cookies with have the same name but belong to different + domains (BACKWARD INCOMPATIBLE) #1125 + + - Support binary Content-Transfer-Encoding #1169 +Platform: UNKNOWN +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Intended Audience :: Developers +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Topic :: Internet :: WWW/HTTP diff --git a/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/SOURCES.txt b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/SOURCES.txt new file mode 100644 index 00000000..029edbd6 --- /dev/null +++ b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/SOURCES.txt @@ -0,0 +1,162 @@ +CHANGES.rst +CONTRIBUTORS.txt +LICENSE.txt +MANIFEST.in +Makefile +README.rst +setup.cfg +setup.py +aiohttp/__init__.py +aiohttp/_websocket.c +aiohttp/_websocket.pyx +aiohttp/_ws_impl.py +aiohttp/abc.py +aiohttp/client.py +aiohttp/client_reqrep.py +aiohttp/client_ws.py +aiohttp/connector.py +aiohttp/cookiejar.py +aiohttp/errors.py +aiohttp/file_sender.py +aiohttp/hdrs.py +aiohttp/helpers.py +aiohttp/log.py +aiohttp/multipart.py +aiohttp/parsers.py +aiohttp/protocol.py +aiohttp/pytest_plugin.py +aiohttp/resolver.py +aiohttp/server.py +aiohttp/signals.py +aiohttp/streams.py +aiohttp/test_utils.py +aiohttp/web.py +aiohttp/web_exceptions.py +aiohttp/web_reqrep.py +aiohttp/web_urldispatcher.py +aiohttp/web_ws.py +aiohttp/worker.py +aiohttp/wsgi.py +aiohttp.egg-info/PKG-INFO +aiohttp.egg-info/SOURCES.txt +aiohttp.egg-info/dependency_links.txt +aiohttp.egg-info/requires.txt +aiohttp.egg-info/top_level.txt +docs/Makefile +docs/abc.rst +docs/aiohttp-icon.ico +docs/aiohttp-icon.svg +docs/api.rst +docs/changes.rst +docs/client.rst +docs/client_reference.rst +docs/conf.py +docs/contributing.rst +docs/faq.rst +docs/glossary.rst +docs/gunicorn.rst +docs/index.rst +docs/logging.rst +docs/make.bat +docs/multipart.rst +docs/new_router.rst +docs/server.rst +docs/spelling_wordlist.txt +docs/streams.rst +docs/testing.rst +docs/tutorial.rst +docs/web.rst +docs/web_reference.rst +docs/_static/aiohttp-icon-128x128.png +docs/_static/aiohttp-icon-32x32.png +docs/_static/aiohttp-icon-64x64.png +docs/_static/aiohttp-icon-96x96.png +examples/background_tasks.py +examples/basic_srv.py +examples/cli_app.py +examples/client_auth.py +examples/client_json.py +examples/client_ws.py +examples/curl.py +examples/fake_server.py +examples/server.crt +examples/server.csr +examples/server.key +examples/static_files.py +examples/web_classview1.py +examples/web_cookies.py +examples/web_rewrite_headers_middleware.py +examples/web_srv.py +examples/web_ws.py +examples/websocket.html +examples/legacy/crawl.py +examples/legacy/srv.py +examples/legacy/tcp_protocol_parser.py +tests/conftest.py +tests/data.unknown_mime_type +tests/hello.txt.gz +tests/sample.crt +tests/sample.crt.der +tests/sample.key +tests/software_development_in_picture.jpg +tests/test_classbasedview.py +tests/test_client_connection.py +tests/test_client_functional.py +tests/test_client_functional_oldstyle.py +tests/test_client_request.py +tests/test_client_response.py +tests/test_client_session.py +tests/test_client_ws.py +tests/test_client_ws_functional.py +tests/test_connector.py +tests/test_cookiejar.py +tests/test_errors.py +tests/test_flowcontrol_streams.py +tests/test_helpers.py +tests/test_http_parser.py +tests/test_multipart.py +tests/test_parser_buffer.py +tests/test_protocol.py +tests/test_proxy.py +tests/test_pytest_plugin.py +tests/test_resolver.py +tests/test_run_app.py +tests/test_server.py +tests/test_signals.py +tests/test_stream_parser.py +tests/test_stream_protocol.py +tests/test_stream_writer.py +tests/test_streams.py +tests/test_test_utils.py +tests/test_urldispatch.py +tests/test_web_application.py +tests/test_web_cli.py +tests/test_web_exceptions.py +tests/test_web_functional.py +tests/test_web_middleware.py +tests/test_web_request.py +tests/test_web_request_handler.py +tests/test_web_response.py +tests/test_web_sendfile.py +tests/test_web_sendfile_functional.py +tests/test_web_urldispatcher.py +tests/test_web_websocket.py +tests/test_web_websocket_functional.py +tests/test_web_websocket_functional_oldstyle.py +tests/test_websocket_handshake.py +tests/test_websocket_parser.py +tests/test_websocket_writer.py +tests/test_worker.py +tests/test_wsgi.py +tests/autobahn/client.py +tests/autobahn/fuzzingclient.json +tests/autobahn/fuzzingserver.json +tests/autobahn/server.py +tests/test_py35/test_cbv35.py +tests/test_py35/test_client.py +tests/test_py35/test_client_websocket_35.py +tests/test_py35/test_multipart_35.py +tests/test_py35/test_resp.py +tests/test_py35/test_streams_35.py +tests/test_py35/test_test_utils_35.py +tests/test_py35/test_web_websocket_35.py \ No newline at end of file diff --git a/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/dependency_links.txt b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/installed-files.txt b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/installed-files.txt new file mode 100644 index 00000000..553a3855 --- /dev/null +++ b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/installed-files.txt @@ -0,0 +1,65 @@ +..\aiohttp\__init__.py +..\aiohttp\__pycache__\__init__.cpython-36.pyc +..\aiohttp\__pycache__\_ws_impl.cpython-36.pyc +..\aiohttp\__pycache__\abc.cpython-36.pyc +..\aiohttp\__pycache__\client.cpython-36.pyc +..\aiohttp\__pycache__\client_reqrep.cpython-36.pyc +..\aiohttp\__pycache__\client_ws.cpython-36.pyc +..\aiohttp\__pycache__\connector.cpython-36.pyc +..\aiohttp\__pycache__\cookiejar.cpython-36.pyc +..\aiohttp\__pycache__\errors.cpython-36.pyc +..\aiohttp\__pycache__\file_sender.cpython-36.pyc +..\aiohttp\__pycache__\hdrs.cpython-36.pyc +..\aiohttp\__pycache__\helpers.cpython-36.pyc +..\aiohttp\__pycache__\log.cpython-36.pyc +..\aiohttp\__pycache__\multipart.cpython-36.pyc +..\aiohttp\__pycache__\parsers.cpython-36.pyc +..\aiohttp\__pycache__\protocol.cpython-36.pyc +..\aiohttp\__pycache__\pytest_plugin.cpython-36.pyc +..\aiohttp\__pycache__\resolver.cpython-36.pyc +..\aiohttp\__pycache__\server.cpython-36.pyc +..\aiohttp\__pycache__\signals.cpython-36.pyc +..\aiohttp\__pycache__\streams.cpython-36.pyc +..\aiohttp\__pycache__\test_utils.cpython-36.pyc +..\aiohttp\__pycache__\web.cpython-36.pyc +..\aiohttp\__pycache__\web_exceptions.cpython-36.pyc +..\aiohttp\__pycache__\web_reqrep.cpython-36.pyc +..\aiohttp\__pycache__\web_urldispatcher.cpython-36.pyc +..\aiohttp\__pycache__\web_ws.cpython-36.pyc +..\aiohttp\__pycache__\worker.cpython-36.pyc +..\aiohttp\__pycache__\wsgi.cpython-36.pyc +..\aiohttp\_websocket.c +..\aiohttp\_websocket.pyx +..\aiohttp\_ws_impl.py +..\aiohttp\abc.py +..\aiohttp\client.py +..\aiohttp\client_reqrep.py +..\aiohttp\client_ws.py +..\aiohttp\connector.py +..\aiohttp\cookiejar.py +..\aiohttp\errors.py +..\aiohttp\file_sender.py +..\aiohttp\hdrs.py +..\aiohttp\helpers.py +..\aiohttp\log.py +..\aiohttp\multipart.py +..\aiohttp\parsers.py +..\aiohttp\protocol.py +..\aiohttp\pytest_plugin.py +..\aiohttp\resolver.py +..\aiohttp\server.py +..\aiohttp\signals.py +..\aiohttp\streams.py +..\aiohttp\test_utils.py +..\aiohttp\web.py +..\aiohttp\web_exceptions.py +..\aiohttp\web_reqrep.py +..\aiohttp\web_urldispatcher.py +..\aiohttp\web_ws.py +..\aiohttp\worker.py +..\aiohttp\wsgi.py +PKG-INFO +SOURCES.txt +dependency_links.txt +requires.txt +top_level.txt diff --git a/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/requires.txt b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/requires.txt new file mode 100644 index 00000000..1621c30e --- /dev/null +++ b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/requires.txt @@ -0,0 +1,3 @@ +chardet +multidict>=2.0 +async_timeout diff --git a/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/top_level.txt b/venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/top_level.txt similarity index 100% rename from venv/Lib/site-packages/aiohttp-3.6.2.dist-info/top_level.txt rename to venv/Lib/site-packages/aiohttp-1.0.5-py3.6.egg-info/top_level.txt diff --git a/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/LICENSE.txt b/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/LICENSE.txt deleted file mode 100644 index 7082a2d5..00000000 --- a/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/LICENSE.txt +++ /dev/null @@ -1,201 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2013-2019 Nikolay Kim and Andrew Svetlov - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/METADATA b/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/METADATA deleted file mode 100644 index c53daffa..00000000 --- a/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/METADATA +++ /dev/null @@ -1,652 +0,0 @@ -Metadata-Version: 2.1 -Name: aiohttp -Version: 3.6.2 -Summary: Async http client/server framework (asyncio) -Home-page: https://github.com/aio-libs/aiohttp -Author: Nikolay Kim -Author-email: fafhrd91@gmail.com -Maintainer: Nikolay Kim , Andrew Svetlov -Maintainer-email: aio-libs@googlegroups.com -License: Apache 2 -Project-URL: Chat: Gitter, https://gitter.im/aio-libs/Lobby -Project-URL: CI: AppVeyor, https://ci.appveyor.com/project/aio-libs/aiohttp -Project-URL: CI: Circle, https://circleci.com/gh/aio-libs/aiohttp -Project-URL: CI: Shippable, https://app.shippable.com/github/aio-libs/aiohttp -Project-URL: CI: Travis, https://travis-ci.com/aio-libs/aiohttp -Project-URL: Coverage: codecov, https://codecov.io/github/aio-libs/aiohttp -Project-URL: Docs: RTD, https://docs.aiohttp.org -Project-URL: GitHub: issues, https://github.com/aio-libs/aiohttp/issues -Project-URL: GitHub: repo, https://github.com/aio-libs/aiohttp -Platform: UNKNOWN -Classifier: License :: OSI Approved :: Apache Software License -Classifier: Intended Audience :: Developers -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Development Status :: 5 - Production/Stable -Classifier: Operating System :: POSIX -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: Microsoft :: Windows -Classifier: Topic :: Internet :: WWW/HTTP -Classifier: Framework :: AsyncIO -Requires-Python: >=3.5.3 -Requires-Dist: attrs (>=17.3.0) -Requires-Dist: chardet (<4.0,>=2.0) -Requires-Dist: multidict (<5.0,>=4.5) -Requires-Dist: async-timeout (<4.0,>=3.0) -Requires-Dist: yarl (<2.0,>=1.0) -Requires-Dist: idna-ssl (>=1.0) ; python_version < "3.7" -Requires-Dist: typing-extensions (>=3.6.5) ; python_version < "3.7" -Provides-Extra: speedups -Requires-Dist: aiodns ; extra == 'speedups' -Requires-Dist: brotlipy ; extra == 'speedups' -Requires-Dist: cchardet ; extra == 'speedups' - -================================== -Async http client/server framework -================================== - -.. image:: https://raw.githubusercontent.com/aio-libs/aiohttp/master/docs/_static/aiohttp-icon-128x128.png - :height: 64px - :width: 64px - :alt: aiohttp logo - -| - -.. image:: https://travis-ci.com/aio-libs/aiohttp.svg?branch=master - :target: https://travis-ci.com/aio-libs/aiohttp - :align: right - :alt: Travis status for master branch - -.. image:: https://ci.appveyor.com/api/projects/status/tnddy9k6pphl8w7k/branch/master?svg=true - :target: https://ci.appveyor.com/project/aio-libs/aiohttp - :align: right - :alt: AppVeyor status for master branch - -.. image:: https://codecov.io/gh/aio-libs/aiohttp/branch/master/graph/badge.svg - :target: https://codecov.io/gh/aio-libs/aiohttp - :alt: codecov.io status for master branch - -.. image:: https://badge.fury.io/py/aiohttp.svg - :target: https://pypi.org/project/aiohttp - :alt: Latest PyPI package version - -.. image:: https://readthedocs.org/projects/aiohttp/badge/?version=latest - :target: https://docs.aiohttp.org/ - :alt: Latest Read The Docs - -.. image:: https://badges.gitter.im/Join%20Chat.svg - :target: https://gitter.im/aio-libs/Lobby - :alt: Chat on Gitter - -Key Features -============ - -- Supports both client and server side of HTTP protocol. -- Supports both client and server Web-Sockets out-of-the-box and avoids - Callback Hell. -- Provides Web-server with middlewares and pluggable routing. - - -Getting started -=============== - -Client ------- - -To get something from the web: - -.. code-block:: python - - import aiohttp - import asyncio - - async def fetch(session, url): - async with session.get(url) as response: - return await response.text() - - async def main(): - async with aiohttp.ClientSession() as session: - html = await fetch(session, 'http://python.org') - print(html) - - if __name__ == '__main__': - loop = asyncio.get_event_loop() - loop.run_until_complete(main()) - - -Server ------- - -An example using a simple server: - -.. code-block:: python - - # examples/server_simple.py - from aiohttp import web - - async def handle(request): - name = request.match_info.get('name', "Anonymous") - text = "Hello, " + name - return web.Response(text=text) - - async def wshandle(request): - ws = web.WebSocketResponse() - await ws.prepare(request) - - async for msg in ws: - if msg.type == web.WSMsgType.text: - await ws.send_str("Hello, {}".format(msg.data)) - elif msg.type == web.WSMsgType.binary: - await ws.send_bytes(msg.data) - elif msg.type == web.WSMsgType.close: - break - - return ws - - - app = web.Application() - app.add_routes([web.get('/', handle), - web.get('/echo', wshandle), - web.get('/{name}', handle)]) - - if __name__ == '__main__': - web.run_app(app) - - -Documentation -============= - -https://aiohttp.readthedocs.io/ - - -Demos -===== - -https://github.com/aio-libs/aiohttp-demos - - -External links -============== - -* `Third party libraries - `_ -* `Built with aiohttp - `_ -* `Powered by aiohttp - `_ - -Feel free to make a Pull Request for adding your link to these pages! - - -Communication channels -====================== - -*aio-libs* google group: https://groups.google.com/forum/#!forum/aio-libs - -Feel free to post your questions and ideas here. - -*gitter chat* https://gitter.im/aio-libs/Lobby - -We support `Stack Overflow -`_. -Please add *aiohttp* tag to your question there. - -Requirements -============ - -- Python >= 3.5.3 -- async-timeout_ -- attrs_ -- chardet_ -- multidict_ -- yarl_ - -Optionally you may install the cChardet_ and aiodns_ libraries (highly -recommended for sake of speed). - -.. _chardet: https://pypi.python.org/pypi/chardet -.. _aiodns: https://pypi.python.org/pypi/aiodns -.. _attrs: https://github.com/python-attrs/attrs -.. _multidict: https://pypi.python.org/pypi/multidict -.. _yarl: https://pypi.python.org/pypi/yarl -.. _async-timeout: https://pypi.python.org/pypi/async_timeout -.. _cChardet: https://pypi.python.org/pypi/cchardet - -License -======= - -``aiohttp`` is offered under the Apache 2 license. - - -Keepsafe -======== - -The aiohttp community would like to thank Keepsafe -(https://www.getkeepsafe.com) for its support in the early days of -the project. - - -Source code -=========== - -The latest developer version is available in a GitHub repository: -https://github.com/aio-libs/aiohttp - -Benchmarks -========== - -If you are interested in efficiency, the AsyncIO community maintains a -list of benchmarks on the official wiki: -https://github.com/python/asyncio/wiki/Benchmarks - -========= -Changelog -========= - -.. - You should *NOT* be adding new change log entries to this file, this - file is managed by towncrier. You *may* edit previous change logs to - fix problems like typo corrections or such. - To add a new change log entry, please see - https://pip.pypa.io/en/latest/development/#adding-a-news-entry - we named the news folder "changes". - - WARNING: Don't drop the next directive! - -.. towncrier release notes start - -3.6.2 (2019-10-09) -================== - -Features --------- - -- Made exceptions pickleable. Also changed the repr of some exceptions. - `#4077 `_ -- Use ``Iterable`` type hint instead of ``Sequence`` for ``Application`` *middleware* - parameter. `#4125 `_ - - -Bugfixes --------- - -- Reset the ``sock_read`` timeout each time data is received for a - ``aiohttp.ClientResponse``. `#3808 - `_ -- Fix handling of expired cookies so they are not stored in CookieJar. - `#4063 `_ -- Fix misleading message in the string representation of ``ClientConnectorError``; - ``self.ssl == None`` means default SSL context, not SSL disabled `#4097 - `_ -- Don't clobber HTTP status when using FileResponse. - `#4106 `_ - - -Improved Documentation ----------------------- - -- Added minimal required logging configuration to logging documentation. - `#2469 `_ -- Update docs to reflect proxy support. - `#4100 `_ -- Fix typo in code example in testing docs. - `#4108 `_ - - -Misc ----- - -- `#4102 `_ - - ----- - - -3.6.1 (2019-09-19) -================== - -Features --------- - -- Compatibility with Python 3.8. - `#4056 `_ - - -Bugfixes --------- - -- correct some exception string format - `#4068 `_ -- Emit a warning when ``ssl.OP_NO_COMPRESSION`` is - unavailable because the runtime is built against - an outdated OpenSSL. - `#4052 `_ -- Update multidict requirement to >= 4.5 - `#4057 `_ - - -Improved Documentation ----------------------- - -- Provide pytest-aiohttp namespace for pytest fixtures in docs. - `#3723 `_ - - ----- - - -3.6.0 (2019-09-06) -================== - -Features --------- - -- Add support for Named Pipes (Site and Connector) under Windows. This feature requires - Proactor event loop to work. `#3629 - `_ -- Removed ``Transfer-Encoding: chunked`` header from websocket responses to be - compatible with more http proxy servers. `#3798 - `_ -- Accept non-GET request for starting websocket handshake on server side. - `#3980 `_ - - -Bugfixes --------- - -- Raise a ClientResponseError instead of an AssertionError for a blank - HTTP Reason Phrase. - `#3532 `_ -- Fix an issue where cookies would sometimes not be set during a redirect. - `#3576 `_ -- Change normalize_path_middleware to use 308 redirect instead of 301. - - This behavior should prevent clients from being unable to use PUT/POST - methods on endpoints that are redirected because of a trailing slash. - `#3579 `_ -- Drop the processed task from ``all_tasks()`` list early. It prevents logging about a - task with unhandled exception when the server is used in conjunction with - ``asyncio.run()``. `#3587 `_ -- ``Signal`` type annotation changed from ``Signal[Callable[['TraceConfig'], - Awaitable[None]]]`` to ``Signal[Callable[ClientSession, SimpleNamespace, ...]``. - `#3595 `_ -- Use sanitized URL as Location header in redirects - `#3614 `_ -- Improve typing annotations for multipart.py along with changes required - by mypy in files that references multipart.py. - `#3621 `_ -- Close session created inside ``aiohttp.request`` when unhandled exception occurs - `#3628 `_ -- Cleanup per-chunk data in generic data read. Memory leak fixed. - `#3631 `_ -- Use correct type for add_view and family - `#3633 `_ -- Fix _keepalive field in __slots__ of ``RequestHandler``. - `#3644 `_ -- Properly handle ConnectionResetError, to silence the "Cannot write to closing - transport" exception when clients disconnect uncleanly. - `#3648 `_ -- Suppress pytest warnings due to ``test_utils`` classes - `#3660 `_ -- Fix overshadowing of overlapped sub-application prefixes. - `#3701 `_ -- Fixed return type annotation for WSMessage.json() - `#3720 `_ -- Properly expose TooManyRedirects publicly as documented. - `#3818 `_ -- Fix missing brackets for IPv6 in proxy CONNECT request - `#3841 `_ -- Make the signature of ``aiohttp.test_utils.TestClient.request`` match - ``asyncio.ClientSession.request`` according to the docs `#3852 - `_ -- Use correct style for re-exported imports, makes mypy ``--strict`` mode happy. - `#3868 `_ -- Fixed type annotation for add_view method of UrlDispatcher to accept any subclass of - View `#3880 `_ -- Made cython HTTP parser set Reason-Phrase of the response to an empty string if it is - missing. `#3906 `_ -- Add URL to the string representation of ClientResponseError. - `#3959 `_ -- Accept ``istr`` keys in ``LooseHeaders`` type hints. - `#3976 `_ -- Fixed race conditions in _resolve_host caching and throttling when tracing is enabled. - `#4013 `_ -- For URLs like "unix://localhost/..." set Host HTTP header to "localhost" instead of - "localhost:None". `#4039 `_ - - -Improved Documentation ----------------------- - -- Modify documentation for Background Tasks to remove deprecated usage of event loop. - `#3526 `_ -- use ``if __name__ == '__main__':`` in server examples. - `#3775 `_ -- Update documentation reference to the default access logger. - `#3783 `_ -- Improve documentation for ``web.BaseRequest.path`` and ``web.BaseRequest.raw_path``. - `#3791 `_ -- Removed deprecation warning in tracing example docs - `#3964 `_ - - ----- - - -3.5.4 (2019-01-12) -================== - -Bugfixes --------- - -- Fix stream ``.read()`` / ``.readany()`` / ``.iter_any()`` which used to return a - partial content only in case of compressed content - `#3525 `_ - - -3.5.3 (2019-01-10) -================== - -Bugfixes --------- - -- Fix type stubs for ``aiohttp.web.run_app(access_log=True)`` and fix edge case of - ``access_log=True`` and the event loop being in debug mode. `#3504 - `_ -- Fix ``aiohttp.ClientTimeout`` type annotations to accept ``None`` for fields - `#3511 `_ -- Send custom per-request cookies even if session jar is empty - `#3515 `_ -- Restore Linux binary wheels publishing on PyPI - ----- - - -3.5.2 (2019-01-08) -================== - -Features --------- - -- ``FileResponse`` from ``web_fileresponse.py`` uses a ``ThreadPoolExecutor`` to work - with files asynchronously. I/O based payloads from ``payload.py`` uses a - ``ThreadPoolExecutor`` to work with I/O objects asynchronously. `#3313 - `_ -- Internal Server Errors in plain text if the browser does not support HTML. - `#3483 `_ - - -Bugfixes --------- - -- Preserve MultipartWriter parts headers on write. Refactor the way how - ``Payload.headers`` are handled. Payload instances now always have headers and - Content-Type defined. Fix Payload Content-Disposition header reset after initial - creation. `#3035 `_ -- Log suppressed exceptions in ``GunicornWebWorker``. - `#3464 `_ -- Remove wildcard imports. - `#3468 `_ -- Use the same task for app initialization and web server handling in gunicorn workers. - It allows to use Python3.7 context vars smoothly. - `#3471 `_ -- Fix handling of chunked+gzipped response when first chunk does not give uncompressed - data `#3477 `_ -- Replace ``collections.MutableMapping`` with ``collections.abc.MutableMapping`` to - avoid a deprecation warning. `#3480 - `_ -- ``Payload.size`` type annotation changed from ``Optional[float]`` to - ``Optional[int]``. `#3484 `_ -- Ignore done tasks when cancels pending activities on ``web.run_app`` finalization. - `#3497 `_ - - -Improved Documentation ----------------------- - -- Add documentation for ``aiohttp.web.HTTPException``. - `#3490 `_ - - -Misc ----- - -- `#3487 `_ - - ----- - - -3.5.1 (2018-12-24) -==================== - -- Fix a regression about ``ClientSession._requote_redirect_url`` modification in debug - mode. - -3.5.0 (2018-12-22) -==================== - -Features --------- - -- The library type annotations are checked in strict mode now. -- Add support for setting cookies for individual request (`#2387 - `_) -- Application.add_domain implementation (`#2809 - `_) -- The default ``app`` in the request returned by ``test_utils.make_mocked_request`` can - now have objects assigned to it and retrieved using the ``[]`` operator. (`#3174 - `_) -- Make ``request.url`` accessible when transport is closed. (`#3177 - `_) -- Add ``zlib_executor_size`` argument to ``Response`` constructor to allow compression - to run in a background executor to avoid blocking the main thread and potentially - triggering health check failures. (`#3205 - `_) -- Enable users to set ``ClientTimeout`` in ``aiohttp.request`` (`#3213 - `_) -- Don't raise a warning if ``NETRC`` environment variable is not set and ``~/.netrc`` - file doesn't exist. (`#3267 `_) -- Add default logging handler to web.run_app If the ``Application.debug``` flag is set - and the default logger ``aiohttp.access`` is used, access logs will now be output - using a *stderr* ``StreamHandler`` if no handlers are attached. Furthermore, if the - default logger has no log level set, the log level will be set to ``DEBUG``. (`#3324 - `_) -- Add method argument to ``session.ws_connect()``. Sometimes server API requires a - different HTTP method for WebSocket connection establishment. For example, ``Docker - exec`` needs POST. (`#3378 `_) -- Create a task per request handling. (`#3406 - `_) - - -Bugfixes --------- - -- Enable passing ``access_log_class`` via ``handler_args`` (`#3158 - `_) -- Return empty bytes with end-of-chunk marker in empty stream reader. (`#3186 - `_) -- Accept ``CIMultiDictProxy`` instances for ``headers`` argument in ``web.Response`` - constructor. (`#3207 `_) -- Don't uppercase HTTP method in parser (`#3233 - `_) -- Make method match regexp RFC-7230 compliant (`#3235 - `_) -- Add ``app.pre_frozen`` state to properly handle startup signals in - sub-applications. (`#3237 `_) -- Enhanced parsing and validation of helpers.BasicAuth.decode. (`#3239 - `_) -- Change imports from collections module in preparation for 3.8. (`#3258 - `_) -- Ensure Host header is added first to ClientRequest to better replicate browser (`#3265 - `_) -- Fix forward compatibility with Python 3.8: importing ABCs directly from the - collections module will not be supported anymore. (`#3273 - `_) -- Keep the query string by ``normalize_path_middleware``. (`#3278 - `_) -- Fix missing parameter ``raise_for_status`` for aiohttp.request() (`#3290 - `_) -- Bracket IPv6 addresses in the HOST header (`#3304 - `_) -- Fix default message for server ping and pong frames. (`#3308 - `_) -- Fix tests/test_connector.py typo and tests/autobahn/server.py duplicate loop - def. (`#3337 `_) -- Fix false-negative indicator end_of_HTTP_chunk in StreamReader.readchunk function - (`#3361 `_) -- Release HTTP response before raising status exception (`#3364 - `_) -- Fix task cancellation when ``sendfile()`` syscall is used by static file - handling. (`#3383 `_) -- Fix stack trace for ``asyncio.TimeoutError`` which was not logged, when it is caught - in the handler. (`#3414 `_) - - -Improved Documentation ----------------------- - -- Improve documentation of ``Application.make_handler`` parameters. (`#3152 - `_) -- Fix BaseRequest.raw_headers doc. (`#3215 - `_) -- Fix typo in TypeError exception reason in ``web.Application._handle`` (`#3229 - `_) -- Make server access log format placeholder %b documentation reflect - behavior and docstring. (`#3307 `_) - - -Deprecations and Removals -------------------------- - -- Deprecate modification of ``session.requote_redirect_url`` (`#2278 - `_) -- Deprecate ``stream.unread_data()`` (`#3260 - `_) -- Deprecated use of boolean in ``resp.enable_compression()`` (`#3318 - `_) -- Encourage creation of aiohttp public objects inside a coroutine (`#3331 - `_) -- Drop dead ``Connection.detach()`` and ``Connection.writer``. Both methods were broken - for more than 2 years. (`#3358 `_) -- Deprecate ``app.loop``, ``request.loop``, ``client.loop`` and ``connector.loop`` - properties. (`#3374 `_) -- Deprecate explicit debug argument. Use asyncio debug mode instead. (`#3381 - `_) -- Deprecate body parameter in HTTPException (and derived classes) constructor. (`#3385 - `_) -- Deprecate bare connector close, use ``async with connector:`` and ``await - connector.close()`` instead. (`#3417 - `_) -- Deprecate obsolete ``read_timeout`` and ``conn_timeout`` in ``ClientSession`` - constructor. (`#3438 `_) - - -Misc ----- - -- #3341, #3351 - diff --git a/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/RECORD b/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/RECORD deleted file mode 100644 index 184dd18d..00000000 --- a/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/RECORD +++ /dev/null @@ -1,124 +0,0 @@ -aiohttp-3.6.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -aiohttp-3.6.2.dist-info/LICENSE.txt,sha256=atcq6P9K6Td0Wq4oBfNDqYf6o6YGrHLGCfLUj3GZspQ,11533 -aiohttp-3.6.2.dist-info/METADATA,sha256=4kebVhrza_aP2QNEcLfPESEhoVd7Jc1une-JuWJlVlE,24410 -aiohttp-3.6.2.dist-info/RECORD,, -aiohttp-3.6.2.dist-info/WHEEL,sha256=uQaeujkjkt7SlmOZGXO6onhwBPrzw2WTI2otbCZzdNI,106 -aiohttp-3.6.2.dist-info/top_level.txt,sha256=iv-JIaacmTl-hSho3QmphcKnbRRYx1st47yjz_178Ro,8 -aiohttp/__init__.py,sha256=k5JorjbCoRvIyRSvcz-N_LFgNe1wX5HtjLCwNkC7zdY,8427 -aiohttp/__pycache__/__init__.cpython-36.pyc,, -aiohttp/__pycache__/abc.cpython-36.pyc,, -aiohttp/__pycache__/base_protocol.cpython-36.pyc,, -aiohttp/__pycache__/client.cpython-36.pyc,, -aiohttp/__pycache__/client_exceptions.cpython-36.pyc,, -aiohttp/__pycache__/client_proto.cpython-36.pyc,, -aiohttp/__pycache__/client_reqrep.cpython-36.pyc,, -aiohttp/__pycache__/client_ws.cpython-36.pyc,, -aiohttp/__pycache__/connector.cpython-36.pyc,, -aiohttp/__pycache__/cookiejar.cpython-36.pyc,, -aiohttp/__pycache__/formdata.cpython-36.pyc,, -aiohttp/__pycache__/frozenlist.cpython-36.pyc,, -aiohttp/__pycache__/hdrs.cpython-36.pyc,, -aiohttp/__pycache__/helpers.cpython-36.pyc,, -aiohttp/__pycache__/http.cpython-36.pyc,, -aiohttp/__pycache__/http_exceptions.cpython-36.pyc,, -aiohttp/__pycache__/http_parser.cpython-36.pyc,, -aiohttp/__pycache__/http_websocket.cpython-36.pyc,, -aiohttp/__pycache__/http_writer.cpython-36.pyc,, -aiohttp/__pycache__/locks.cpython-36.pyc,, -aiohttp/__pycache__/log.cpython-36.pyc,, -aiohttp/__pycache__/multipart.cpython-36.pyc,, -aiohttp/__pycache__/payload.cpython-36.pyc,, -aiohttp/__pycache__/payload_streamer.cpython-36.pyc,, -aiohttp/__pycache__/pytest_plugin.cpython-36.pyc,, -aiohttp/__pycache__/resolver.cpython-36.pyc,, -aiohttp/__pycache__/signals.cpython-36.pyc,, -aiohttp/__pycache__/streams.cpython-36.pyc,, -aiohttp/__pycache__/tcp_helpers.cpython-36.pyc,, -aiohttp/__pycache__/test_utils.cpython-36.pyc,, -aiohttp/__pycache__/tracing.cpython-36.pyc,, -aiohttp/__pycache__/typedefs.cpython-36.pyc,, -aiohttp/__pycache__/web.cpython-36.pyc,, -aiohttp/__pycache__/web_app.cpython-36.pyc,, -aiohttp/__pycache__/web_exceptions.cpython-36.pyc,, -aiohttp/__pycache__/web_fileresponse.cpython-36.pyc,, -aiohttp/__pycache__/web_log.cpython-36.pyc,, -aiohttp/__pycache__/web_middlewares.cpython-36.pyc,, -aiohttp/__pycache__/web_protocol.cpython-36.pyc,, -aiohttp/__pycache__/web_request.cpython-36.pyc,, -aiohttp/__pycache__/web_response.cpython-36.pyc,, -aiohttp/__pycache__/web_routedef.cpython-36.pyc,, -aiohttp/__pycache__/web_runner.cpython-36.pyc,, -aiohttp/__pycache__/web_server.cpython-36.pyc,, -aiohttp/__pycache__/web_urldispatcher.cpython-36.pyc,, -aiohttp/__pycache__/web_ws.cpython-36.pyc,, -aiohttp/__pycache__/worker.cpython-36.pyc,, -aiohttp/_cparser.pxd,sha256=xvsLl13ZXXyHGyb2Us7WsLncndQrxhyGB4KXnvbsRtQ,4099 -aiohttp/_find_header.c,sha256=MOZn07_ot-UcOdQBpYAWQmyigqLvMwkqa_7l4M7D1dI,199932 -aiohttp/_find_header.h,sha256=HistyxY7K3xEJ53Y5xEfwrDVDkfcV0zQ9mkzMgzi_jo,184 -aiohttp/_find_header.pxd,sha256=BFUSmxhemBtblqxzjzH3x03FfxaWlTyuAIOz8YZ5_nM,70 -aiohttp/_frozenlist.c,sha256=-vfgzV6cNjUykuqt1kkWDiT2U92BR2zhL9b9yDiiodg,288943 -aiohttp/_frozenlist.cp36-win_amd64.pyd,sha256=SN72FLXG8KJYhqgT9BtULfLFhjSmvv_C-oDeQPhlpH8,79872 -aiohttp/_frozenlist.pyx,sha256=SB851KmtWpiJ2ZB05Tpo4855VkCyRtgMs843Wz8kFeg,2713 -aiohttp/_headers.pxi,sha256=PxiakDsuEs0O94eHRlPcerO24TqPAxc0BtX86XZL4gw,2111 -aiohttp/_helpers.c,sha256=sQcHpEGAX3jEvA8jujh4_D_fev9cRjMAc5CySqtHYrg,208657 -aiohttp/_helpers.cp36-win_amd64.pyd,sha256=ezuDwotCokL_pvZWHfe9kppSqetibStK3Ob727IJaGY,59904 -aiohttp/_helpers.pyi,sha256=C6Q4W8EwElvD1gF1siRGMVG7evEX8fWWstZHL1BbsDA,212 -aiohttp/_helpers.pyx,sha256=tgl7fZh0QMT6cjf4jSJ8iaO6DdQD3GON2-SH4N5_ETg,1084 -aiohttp/_http_parser.c,sha256=W1sETtDrrBdnBiSOpqaDcO9DcE9zhyLjPTq4WKIK0bc,997494 -aiohttp/_http_parser.cp36-win_amd64.pyd,sha256=E54uSiDD1EJj7fCWuOxxqGJKzvCif6HV5ewK1US3ya8,255488 -aiohttp/_http_parser.pyx,sha256=C2XxooYRput7XPQzbaGMDrtvJtmhWa58SDPytyuAwGk,29577 -aiohttp/_http_writer.c,sha256=-wuBZwiaUXEy1Zj-R5BD5igH7cUg_CYb5ZvYMsh8vzo,211620 -aiohttp/_http_writer.cp36-win_amd64.pyd,sha256=wsDiKyfAERR76tMESHKZ9xsEABBowsdYWKjvF7xv2fs,51712 -aiohttp/_http_writer.pyx,sha256=TzCawCBLMe7w9eX2SEcUcLYySwkFfrfjaEYHS0Uvjtg,4353 -aiohttp/_websocket.c,sha256=JrG6bXW3OR8sfxl5V1Q3VTXvGBbFTYgzgdbhQHr3LGI,136606 -aiohttp/_websocket.cp36-win_amd64.pyd,sha256=JvOl8VKDwvfhr3TDGovNSUYK_8smCphWhewuKzk4l1Y,39424 -aiohttp/_websocket.pyx,sha256=Ig8jXl_wkAXPugEWS0oPYo0-BnL8zT7uBG6BrYqVXdA,1613 -aiohttp/abc.py,sha256=s3wtDI3os8uX4FdQbsvJwr67cFGhylif0mR5k2SKY04,5600 -aiohttp/base_protocol.py,sha256=5PJImwc0iX8kR3VjZn1D_SAeL-6JKERi87iGHEYjJQ4,2744 -aiohttp/client.py,sha256=DYv-h8V2wljt4hRmPDmU2czk9zSlSn8zua9MgssSEiY,45130 -aiohttp/client_exceptions.py,sha256=RCbzCGw_HcaqnL4AHf3nol32xH_2xu1hrYbLNgpjHqk,8786 -aiohttp/client_proto.py,sha256=XDXJ0G9RW8m80wHahzjgp4T5S3Rf6LSYks9Q9MajSQg,8276 -aiohttp/client_reqrep.py,sha256=zf6GFaDYvpy50HZ4GntrT8flcc6B4HfwnlHw_yYdGMw,37064 -aiohttp/client_ws.py,sha256=OUkkw9RwRHRmAakBibE6c63VLMWGVgoyRadoC22wtNY,10995 -aiohttp/connector.py,sha256=pbq2XHrujiyQXbIhzXQK6E1zrzRYedzt8xlGNmvbQcM,43672 -aiohttp/cookiejar.py,sha256=lNwvnGX3BjIDU4btE50AUsBQditLXzJhsPPUMZo-dkI,12249 -aiohttp/formdata.py,sha256=1yNFnS6O0wUrIL4_V66-DwyjS3nWVd0JiPIjWKbTZTs,5957 -aiohttp/frozenlist.py,sha256=PSElO5biFCVHyVEr6-hXy7--cDaHAxaWDrsFxESHsFc,1853 -aiohttp/frozenlist.pyi,sha256=z-EGiL4Q5MTe1wxDZINsIhqh4Eb0oT9Xn0X_Rt7C9ns,1512 -aiohttp/hdrs.py,sha256=PmN2SUiMmwiC0TMEEMSFfwirUpnrzy3jwUhniPGFlmc,3549 -aiohttp/helpers.py,sha256=yAdG1c-axo7-Vsf3CRaEqb7hU5Ej-FpUgZowGA76f_U,23613 -aiohttp/http.py,sha256=H9xNqvagxteFvx2R7AeYiGfze7uR6VKF5IsUAITr7d4,2183 -aiohttp/http_exceptions.py,sha256=Oby70EpyDmwpsb4DpCFYXw-sa856HmWv8IjeHlWWlJo,2771 -aiohttp/http_parser.py,sha256=Ttk5BSX11cXMaFJmquzd1oNkZbnodghQvBgdUGdQxnE,28676 -aiohttp/http_websocket.py,sha256=KmHznrwSjtpUgxbFafBg1MaAaCpxGxoK0IL8wDKg9f8,25400 -aiohttp/http_writer.py,sha256=VBMPy_AaB7m_keycuu05SCN2S3GVVyY8UCHG-W86Y1w,5411 -aiohttp/locks.py,sha256=6DiJHW1eQKXypu1eWXZT3_amPhFBK-jnxdI-_BpYICk,1278 -aiohttp/log.py,sha256=qAQMjI6XpX3MOAZATN4HcG0tIceSreR54orlYZaoJ0A,333 -aiohttp/multipart.py,sha256=RPXfp5GMauxW19nbBaLAkzgUFKTQ9eMo4XtZ7ItGyo4,33740 -aiohttp/payload.py,sha256=lCF_pZvwyBKJGk4OOLYEQhtxUwOW8rsFF0pxisvfBps,14483 -aiohttp/payload_streamer.py,sha256=7koj4FVujDGriDIOes48XPp5BK9tsWYyTxJG-3aNaHc,2177 -aiohttp/py.typed,sha256=E84IaZyFwfLqvXjOVW4LS6WH7QOaKEFpNh9TFyzHNQc,6 -aiohttp/pytest_plugin.py,sha256=1_XNSrZS-czuaNVt4qvRQs-GbIIl8DaLykGpoDlZfhU,11187 -aiohttp/resolver.py,sha256=mQvusmMHpS0JekvnX7R1y4aqQ7BIIv3FIkxO5wgv2xQ,3738 -aiohttp/signals.py,sha256=I_QAX1S7VbN7KDnNO6CSnAzhzx42AYh2Dto_FC9DQ3k,982 -aiohttp/signals.pyi,sha256=pg4KElFcxBNFU-OQpTe2x-7qKJ79bAlemgqE-yaciiU,341 -aiohttp/streams.py,sha256=EPM7T5_aJLOXlBTIEeFapIQ1O33KsHTvT-wWH3X0QvQ,21093 -aiohttp/tcp_helpers.py,sha256=q9fHztjKbR57sCc4zWoo89QDW88pLT0OpcdHLGcV3Fo,1694 -aiohttp/test_utils.py,sha256=_GjrPdE_9v0SxzbM4Tmt8vst-KJPwL2ILM_Rl1jHhi4,21530 -aiohttp/tracing.py,sha256=GGhlQDrx5AVwFt33Zl4DvBIoFcR7sXAsgXNxvkd2Uus,13740 -aiohttp/typedefs.py,sha256=o4R9uAySHxTzedIfX3UPbD0a5TnD5inc_M-h_4qyC4U,1377 -aiohttp/web.py,sha256=KQXp0C__KpeX8nYM3FWl-eoMAmj9LZIbx7YeI39pQco,19940 -aiohttp/web_app.py,sha256=dHOhoDoakwdrya0cc6Jl6K723MKGmd_M5LxH3wDeGQI,17779 -aiohttp/web_exceptions.py,sha256=CQvslnHcpFnreO-qNjnKOWQev7ZvlTG6jfV14NQwb1Q,10519 -aiohttp/web_fileresponse.py,sha256=TftBNfbgowCQ0L5Iud-dewCAnXq5tIyP-8iZ-KrSHw8,13118 -aiohttp/web_log.py,sha256=gOR8iLbhjeAUwGL-21qD31kA0HlYSNhpdX6eNwJ-3Uo,8490 -aiohttp/web_middlewares.py,sha256=jATe_igeeoyBoWKBDW_ISOOzFKvxSoLJE1QPTqZPWGc,4310 -aiohttp/web_protocol.py,sha256=Zol5oVApIE12NDLBV_W1oKW8AN-sGdBfC0RFMI050U0,22791 -aiohttp/web_request.py,sha256=xzvj84uGe5Uuug1b4iKWZl8uko_0TpzYKa00POke_NM,26526 -aiohttp/web_response.py,sha256=CEx04E7NLNg6mfgTjT0QPS9vJuglbw3UQvwob6Qeb7c,26202 -aiohttp/web_routedef.py,sha256=5QCl85zQml2qoj7bkC9XMoK4stBVuUoiq_0uefxifjc,6293 -aiohttp/web_runner.py,sha256=ArW4NjMJ24Fv68Ez-9hPL1WNzVygDYEWJ4aIfzOMKz8,11479 -aiohttp/web_server.py,sha256=P826xDCDs4VgeksMam8OHKm_VzprXuOpsJrysqj3CVg,2222 -aiohttp/web_urldispatcher.py,sha256=8uhNNXlHd2WJfJ4wcyQ1UxoRM1VUyWWwQhK-TPrM_GM,40043 -aiohttp/web_ws.py,sha256=mAU6Ln3AbMZeXjUZSSA5MmE39hTajJIMxBE0xnq-4Tc,17414 -aiohttp/worker.py,sha256=yatPZxpUOp9CzDA05Jb2UWi0eo2PgGWlQm4lIFCRCSY,8420 diff --git a/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/WHEEL b/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/WHEEL deleted file mode 100644 index 3740b8bc..00000000 --- a/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.6) -Root-Is-Purelib: false -Tag: cp36-cp36m-win_amd64 - diff --git a/venv/Lib/site-packages/aiohttp/__init__.py b/venv/Lib/site-packages/aiohttp/__init__.py index 58149e26..f7090160 100644 --- a/venv/Lib/site-packages/aiohttp/__init__.py +++ b/venv/Lib/site-packages/aiohttp/__init__.py @@ -1,226 +1,41 @@ -__version__ = '3.6.2' +__version__ = '1.0.5' -from typing import Tuple # noqa +# Deprecated, keep it here for a while for backward compatibility. +import multidict # noqa -from . import hdrs as hdrs -from .client import BaseConnector as BaseConnector -from .client import ClientConnectionError as ClientConnectionError -from .client import ( - ClientConnectorCertificateError as ClientConnectorCertificateError, -) -from .client import ClientConnectorError as ClientConnectorError -from .client import ClientConnectorSSLError as ClientConnectorSSLError -from .client import ClientError as ClientError -from .client import ClientHttpProxyError as ClientHttpProxyError -from .client import ClientOSError as ClientOSError -from .client import ClientPayloadError as ClientPayloadError -from .client import ClientProxyConnectionError as ClientProxyConnectionError -from .client import ClientRequest as ClientRequest -from .client import ClientResponse as ClientResponse -from .client import ClientResponseError as ClientResponseError -from .client import ClientSession as ClientSession -from .client import ClientSSLError as ClientSSLError -from .client import ClientTimeout as ClientTimeout -from .client import ClientWebSocketResponse as ClientWebSocketResponse -from .client import ContentTypeError as ContentTypeError -from .client import Fingerprint as Fingerprint -from .client import InvalidURL as InvalidURL -from .client import NamedPipeConnector as NamedPipeConnector -from .client import RequestInfo as RequestInfo -from .client import ServerConnectionError as ServerConnectionError -from .client import ServerDisconnectedError as ServerDisconnectedError -from .client import ServerFingerprintMismatch as ServerFingerprintMismatch -from .client import ServerTimeoutError as ServerTimeoutError -from .client import TCPConnector as TCPConnector -from .client import TooManyRedirects as TooManyRedirects -from .client import UnixConnector as UnixConnector -from .client import WSServerHandshakeError as WSServerHandshakeError -from .client import request as request -from .cookiejar import CookieJar as CookieJar -from .cookiejar import DummyCookieJar as DummyCookieJar -from .formdata import FormData as FormData -from .helpers import BasicAuth as BasicAuth -from .helpers import ChainMapProxy as ChainMapProxy -from .http import HttpVersion as HttpVersion -from .http import HttpVersion10 as HttpVersion10 -from .http import HttpVersion11 as HttpVersion11 -from .http import WebSocketError as WebSocketError -from .http import WSCloseCode as WSCloseCode -from .http import WSMessage as WSMessage -from .http import WSMsgType as WSMsgType -from .multipart import ( - BadContentDispositionHeader as BadContentDispositionHeader, -) -from .multipart import BadContentDispositionParam as BadContentDispositionParam -from .multipart import BodyPartReader as BodyPartReader -from .multipart import MultipartReader as MultipartReader -from .multipart import MultipartWriter as MultipartWriter -from .multipart import ( - content_disposition_filename as content_disposition_filename, -) -from .multipart import parse_content_disposition as parse_content_disposition -from .payload import PAYLOAD_REGISTRY as PAYLOAD_REGISTRY -from .payload import AsyncIterablePayload as AsyncIterablePayload -from .payload import BufferedReaderPayload as BufferedReaderPayload -from .payload import BytesIOPayload as BytesIOPayload -from .payload import BytesPayload as BytesPayload -from .payload import IOBasePayload as IOBasePayload -from .payload import JsonPayload as JsonPayload -from .payload import Payload as Payload -from .payload import StringIOPayload as StringIOPayload -from .payload import StringPayload as StringPayload -from .payload import TextIOPayload as TextIOPayload -from .payload import get_payload as get_payload -from .payload import payload_type as payload_type -from .payload_streamer import streamer as streamer -from .resolver import AsyncResolver as AsyncResolver -from .resolver import DefaultResolver as DefaultResolver -from .resolver import ThreadedResolver as ThreadedResolver -from .signals import Signal as Signal -from .streams import EMPTY_PAYLOAD as EMPTY_PAYLOAD -from .streams import DataQueue as DataQueue -from .streams import EofStream as EofStream -from .streams import FlowControlDataQueue as FlowControlDataQueue -from .streams import StreamReader as StreamReader -from .tracing import TraceConfig as TraceConfig -from .tracing import ( - TraceConnectionCreateEndParams as TraceConnectionCreateEndParams, -) -from .tracing import ( - TraceConnectionCreateStartParams as TraceConnectionCreateStartParams, -) -from .tracing import ( - TraceConnectionQueuedEndParams as TraceConnectionQueuedEndParams, -) -from .tracing import ( - TraceConnectionQueuedStartParams as TraceConnectionQueuedStartParams, -) -from .tracing import ( - TraceConnectionReuseconnParams as TraceConnectionReuseconnParams, -) -from .tracing import TraceDnsCacheHitParams as TraceDnsCacheHitParams -from .tracing import TraceDnsCacheMissParams as TraceDnsCacheMissParams -from .tracing import ( - TraceDnsResolveHostEndParams as TraceDnsResolveHostEndParams, -) -from .tracing import ( - TraceDnsResolveHostStartParams as TraceDnsResolveHostStartParams, -) -from .tracing import TraceRequestChunkSentParams as TraceRequestChunkSentParams -from .tracing import TraceRequestEndParams as TraceRequestEndParams -from .tracing import TraceRequestExceptionParams as TraceRequestExceptionParams -from .tracing import TraceRequestRedirectParams as TraceRequestRedirectParams -from .tracing import TraceRequestStartParams as TraceRequestStartParams -from .tracing import ( - TraceResponseChunkReceivedParams as TraceResponseChunkReceivedParams, -) +# This relies on each of the submodules having an __all__ variable. -__all__ = ( - 'hdrs', - # client - 'BaseConnector', - 'ClientConnectionError', - 'ClientConnectorCertificateError', - 'ClientConnectorError', - 'ClientConnectorSSLError', - 'ClientError', - 'ClientHttpProxyError', - 'ClientOSError', - 'ClientPayloadError', - 'ClientProxyConnectionError', - 'ClientResponse', - 'ClientRequest', - 'ClientResponseError', - 'ClientSSLError', - 'ClientSession', - 'ClientTimeout', - 'ClientWebSocketResponse', - 'ContentTypeError', - 'Fingerprint', - 'InvalidURL', - 'RequestInfo', - 'ServerConnectionError', - 'ServerDisconnectedError', - 'ServerFingerprintMismatch', - 'ServerTimeoutError', - 'TCPConnector', - 'TooManyRedirects', - 'UnixConnector', - 'NamedPipeConnector', - 'WSServerHandshakeError', - 'request', - # cookiejar - 'CookieJar', - 'DummyCookieJar', - # formdata - 'FormData', - # helpers - 'BasicAuth', - 'ChainMapProxy', - # http - 'HttpVersion', - 'HttpVersion10', - 'HttpVersion11', - 'WSMsgType', - 'WSCloseCode', - 'WSMessage', - 'WebSocketError', - # multipart - 'BadContentDispositionHeader', - 'BadContentDispositionParam', - 'BodyPartReader', - 'MultipartReader', - 'MultipartWriter', - 'content_disposition_filename', - 'parse_content_disposition', - # payload - 'AsyncIterablePayload', - 'BufferedReaderPayload', - 'BytesIOPayload', - 'BytesPayload', - 'IOBasePayload', - 'JsonPayload', - 'PAYLOAD_REGISTRY', - 'Payload', - 'StringIOPayload', - 'StringPayload', - 'TextIOPayload', - 'get_payload', - 'payload_type', - # payload_streamer - 'streamer', - # resolver - 'AsyncResolver', - 'DefaultResolver', - 'ThreadedResolver', - # signals - 'Signal', - 'DataQueue', - 'EMPTY_PAYLOAD', - 'EofStream', - 'FlowControlDataQueue', - 'StreamReader', - # tracing - 'TraceConfig', - 'TraceConnectionCreateEndParams', - 'TraceConnectionCreateStartParams', - 'TraceConnectionQueuedEndParams', - 'TraceConnectionQueuedStartParams', - 'TraceConnectionReuseconnParams', - 'TraceDnsCacheHitParams', - 'TraceDnsCacheMissParams', - 'TraceDnsResolveHostEndParams', - 'TraceDnsResolveHostStartParams', - 'TraceRequestChunkSentParams', - 'TraceRequestEndParams', - 'TraceRequestExceptionParams', - 'TraceRequestRedirectParams', - 'TraceRequestStartParams', - 'TraceResponseChunkReceivedParams', -) # type: Tuple[str, ...] +from multidict import * # noqa +from . import hdrs # noqa +from .protocol import * # noqa +from .connector import * # noqa +from .client import * # noqa +from .client_reqrep import * # noqa +from .errors import * # noqa +from .helpers import * # noqa +from .parsers import * # noqa +from .streams import * # noqa +from .multipart import * # noqa +from .client_ws import ClientWebSocketResponse # noqa +from ._ws_impl import WSMsgType, WSCloseCode, WSMessage, WebSocketError # noqa +from .file_sender import FileSender # noqa +from .cookiejar import CookieJar # noqa +from .resolver import * # noqa -try: - from .worker import GunicornWebWorker, GunicornUVLoopWebWorker # noqa - __all__ += ('GunicornWebWorker', 'GunicornUVLoopWebWorker') -except ImportError: # pragma: no cover - pass + +MsgType = WSMsgType # backward compatibility + + +__all__ = (client.__all__ + # noqa + client_reqrep.__all__ + # noqa + errors.__all__ + # noqa + helpers.__all__ + # noqa + parsers.__all__ + # noqa + protocol.__all__ + # noqa + connector.__all__ + # noqa + streams.__all__ + # noqa + multidict.__all__ + # noqa + multipart.__all__ + # noqa + ('hdrs', 'FileSender', 'WSMsgType', 'MsgType', 'WSCloseCode', + 'WebSocketError', 'WSMessage', + 'ClientWebSocketResponse', 'CookieJar')) diff --git a/venv/Lib/site-packages/aiohttp/_cparser.pxd b/venv/Lib/site-packages/aiohttp/_cparser.pxd deleted file mode 100644 index 0f9fc009..00000000 --- a/venv/Lib/site-packages/aiohttp/_cparser.pxd +++ /dev/null @@ -1,140 +0,0 @@ -from libc.stdint cimport uint16_t, uint32_t, uint64_t - - -cdef extern from "../vendor/http-parser/http_parser.h": - ctypedef int (*http_data_cb) (http_parser*, - const char *at, - size_t length) except -1 - - ctypedef int (*http_cb) (http_parser*) except -1 - - struct http_parser: - unsigned int type - unsigned int flags - unsigned int state - unsigned int header_state - unsigned int index - - uint32_t nread - uint64_t content_length - - unsigned short http_major - unsigned short http_minor - unsigned int status_code - unsigned int method - unsigned int http_errno - - unsigned int upgrade - - void *data - - struct http_parser_settings: - http_cb on_message_begin - http_data_cb on_url - http_data_cb on_status - http_data_cb on_header_field - http_data_cb on_header_value - http_cb on_headers_complete - http_data_cb on_body - http_cb on_message_complete - http_cb on_chunk_header - http_cb on_chunk_complete - - enum http_parser_type: - HTTP_REQUEST, - HTTP_RESPONSE, - HTTP_BOTH - - enum http_errno: - HPE_OK, - HPE_CB_message_begin, - HPE_CB_url, - HPE_CB_header_field, - HPE_CB_header_value, - HPE_CB_headers_complete, - HPE_CB_body, - HPE_CB_message_complete, - HPE_CB_status, - HPE_CB_chunk_header, - HPE_CB_chunk_complete, - HPE_INVALID_EOF_STATE, - HPE_HEADER_OVERFLOW, - HPE_CLOSED_CONNECTION, - HPE_INVALID_VERSION, - HPE_INVALID_STATUS, - HPE_INVALID_METHOD, - HPE_INVALID_URL, - HPE_INVALID_HOST, - HPE_INVALID_PORT, - HPE_INVALID_PATH, - HPE_INVALID_QUERY_STRING, - HPE_INVALID_FRAGMENT, - HPE_LF_EXPECTED, - HPE_INVALID_HEADER_TOKEN, - HPE_INVALID_CONTENT_LENGTH, - HPE_INVALID_CHUNK_SIZE, - HPE_INVALID_CONSTANT, - HPE_INVALID_INTERNAL_STATE, - HPE_STRICT, - HPE_PAUSED, - HPE_UNKNOWN - - enum flags: - F_CHUNKED, - F_CONNECTION_KEEP_ALIVE, - F_CONNECTION_CLOSE, - F_CONNECTION_UPGRADE, - F_TRAILING, - F_UPGRADE, - F_SKIPBODY, - F_CONTENTLENGTH - - enum http_method: - DELETE, GET, HEAD, POST, PUT, CONNECT, OPTIONS, TRACE, COPY, - LOCK, MKCOL, MOVE, PROPFIND, PROPPATCH, SEARCH, UNLOCK, BIND, - REBIND, UNBIND, ACL, REPORT, MKACTIVITY, CHECKOUT, MERGE, - MSEARCH, NOTIFY, SUBSCRIBE, UNSUBSCRIBE, PATCH, PURGE, MKCALENDAR, - LINK, UNLINK - - void http_parser_init(http_parser *parser, http_parser_type type) - - size_t http_parser_execute(http_parser *parser, - const http_parser_settings *settings, - const char *data, - size_t len) - - int http_should_keep_alive(const http_parser *parser) - - void http_parser_settings_init(http_parser_settings *settings) - - const char *http_errno_name(http_errno err) - const char *http_errno_description(http_errno err) - const char *http_method_str(http_method m) - - # URL Parser - - enum http_parser_url_fields: - UF_SCHEMA = 0, - UF_HOST = 1, - UF_PORT = 2, - UF_PATH = 3, - UF_QUERY = 4, - UF_FRAGMENT = 5, - UF_USERINFO = 6, - UF_MAX = 7 - - struct http_parser_url_field_data: - uint16_t off - uint16_t len - - struct http_parser_url: - uint16_t field_set - uint16_t port - http_parser_url_field_data[UF_MAX] field_data - - void http_parser_url_init(http_parser_url *u) - - int http_parser_parse_url(const char *buf, - size_t buflen, - int is_connect, - http_parser_url *u) diff --git a/venv/Lib/site-packages/aiohttp/_find_header.c b/venv/Lib/site-packages/aiohttp/_find_header.c deleted file mode 100644 index fbc6c4f0..00000000 --- a/venv/Lib/site-packages/aiohttp/_find_header.c +++ /dev/null @@ -1,10000 +0,0 @@ -/* The file is autogenerated from aiohttp/hdrs.py -Run ./tools/gen.py to update it after the origin changing. */ - -#include "_find_header.h" - -#define NEXT_CHAR() \ -{ \ - count++; \ - if (count == size) { \ - /* end of search */ \ - return -1; \ - } \ - pchar++; \ - ch = *pchar; \ - last = (count == size -1); \ -} while(0); - -int -find_header(const char *str, int size) -{ - char *pchar = str; - int last; - char ch; - int count = -1; - pchar--; - -INITIAL: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto A; - case 'a': - if (last) { - return -1; - } - goto A; - case 'C': - if (last) { - return -1; - } - goto C; - case 'c': - if (last) { - return -1; - } - goto C; - case 'D': - if (last) { - return -1; - } - goto D; - case 'd': - if (last) { - return -1; - } - goto D; - case 'E': - if (last) { - return -1; - } - goto E; - case 'e': - if (last) { - return -1; - } - goto E; - case 'F': - if (last) { - return -1; - } - goto F; - case 'f': - if (last) { - return -1; - } - goto F; - case 'H': - if (last) { - return -1; - } - goto H; - case 'h': - if (last) { - return -1; - } - goto H; - case 'I': - if (last) { - return -1; - } - goto I; - case 'i': - if (last) { - return -1; - } - goto I; - case 'K': - if (last) { - return -1; - } - goto K; - case 'k': - if (last) { - return -1; - } - goto K; - case 'L': - if (last) { - return -1; - } - goto L; - case 'l': - if (last) { - return -1; - } - goto L; - case 'M': - if (last) { - return -1; - } - goto M; - case 'm': - if (last) { - return -1; - } - goto M; - case 'O': - if (last) { - return -1; - } - goto O; - case 'o': - if (last) { - return -1; - } - goto O; - case 'P': - if (last) { - return -1; - } - goto P; - case 'p': - if (last) { - return -1; - } - goto P; - case 'R': - if (last) { - return -1; - } - goto R; - case 'r': - if (last) { - return -1; - } - goto R; - case 'S': - if (last) { - return -1; - } - goto S; - case 's': - if (last) { - return -1; - } - goto S; - case 'T': - if (last) { - return -1; - } - goto T; - case 't': - if (last) { - return -1; - } - goto T; - case 'U': - if (last) { - return -1; - } - goto U; - case 'u': - if (last) { - return -1; - } - goto U; - case 'V': - if (last) { - return -1; - } - goto V; - case 'v': - if (last) { - return -1; - } - goto V; - case 'W': - if (last) { - return -1; - } - goto W; - case 'w': - if (last) { - return -1; - } - goto W; - case 'X': - if (last) { - return -1; - } - goto X; - case 'x': - if (last) { - return -1; - } - goto X; - default: - return -1; - } - -A: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto AC; - case 'c': - if (last) { - return -1; - } - goto AC; - case 'G': - if (last) { - return -1; - } - goto AG; - case 'g': - if (last) { - return -1; - } - goto AG; - case 'L': - if (last) { - return -1; - } - goto AL; - case 'l': - if (last) { - return -1; - } - goto AL; - case 'U': - if (last) { - return -1; - } - goto AU; - case 'u': - if (last) { - return -1; - } - goto AU; - default: - return -1; - } - -AC: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto ACC; - case 'c': - if (last) { - return -1; - } - goto ACC; - default: - return -1; - } - -ACC: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCE; - case 'e': - if (last) { - return -1; - } - goto ACCE; - default: - return -1; - } - -ACCE: - NEXT_CHAR(); - switch (ch) { - case 'P': - if (last) { - return -1; - } - goto ACCEP; - case 'p': - if (last) { - return -1; - } - goto ACCEP; - case 'S': - if (last) { - return -1; - } - goto ACCES; - case 's': - if (last) { - return -1; - } - goto ACCES; - default: - return -1; - } - -ACCEP: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return 0; - } - goto ACCEPT; - case 't': - if (last) { - return 0; - } - goto ACCEPT; - default: - return -1; - } - -ACCEPT: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto ACCEPT_; - default: - return -1; - } - -ACCEPT_: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto ACCEPT_C; - case 'c': - if (last) { - return -1; - } - goto ACCEPT_C; - case 'E': - if (last) { - return -1; - } - goto ACCEPT_E; - case 'e': - if (last) { - return -1; - } - goto ACCEPT_E; - case 'L': - if (last) { - return -1; - } - goto ACCEPT_L; - case 'l': - if (last) { - return -1; - } - goto ACCEPT_L; - case 'R': - if (last) { - return -1; - } - goto ACCEPT_R; - case 'r': - if (last) { - return -1; - } - goto ACCEPT_R; - default: - return -1; - } - -ACCEPT_C: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return -1; - } - goto ACCEPT_CH; - case 'h': - if (last) { - return -1; - } - goto ACCEPT_CH; - default: - return -1; - } - -ACCEPT_CH: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCEPT_CHA; - case 'a': - if (last) { - return -1; - } - goto ACCEPT_CHA; - default: - return -1; - } - -ACCEPT_CHA: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto ACCEPT_CHAR; - case 'r': - if (last) { - return -1; - } - goto ACCEPT_CHAR; - default: - return -1; - } - -ACCEPT_CHAR: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto ACCEPT_CHARS; - case 's': - if (last) { - return -1; - } - goto ACCEPT_CHARS; - default: - return -1; - } - -ACCEPT_CHARS: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCEPT_CHARSE; - case 'e': - if (last) { - return -1; - } - goto ACCEPT_CHARSE; - default: - return -1; - } - -ACCEPT_CHARSE: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return 1; - } - goto ACCEPT_CHARSET; - case 't': - if (last) { - return 1; - } - goto ACCEPT_CHARSET; - default: - return -1; - } - -ACCEPT_E: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto ACCEPT_EN; - case 'n': - if (last) { - return -1; - } - goto ACCEPT_EN; - default: - return -1; - } - -ACCEPT_EN: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto ACCEPT_ENC; - case 'c': - if (last) { - return -1; - } - goto ACCEPT_ENC; - default: - return -1; - } - -ACCEPT_ENC: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto ACCEPT_ENCO; - case 'o': - if (last) { - return -1; - } - goto ACCEPT_ENCO; - default: - return -1; - } - -ACCEPT_ENCO: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto ACCEPT_ENCOD; - case 'd': - if (last) { - return -1; - } - goto ACCEPT_ENCOD; - default: - return -1; - } - -ACCEPT_ENCOD: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto ACCEPT_ENCODI; - case 'i': - if (last) { - return -1; - } - goto ACCEPT_ENCODI; - default: - return -1; - } - -ACCEPT_ENCODI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto ACCEPT_ENCODIN; - case 'n': - if (last) { - return -1; - } - goto ACCEPT_ENCODIN; - default: - return -1; - } - -ACCEPT_ENCODIN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return 2; - } - goto ACCEPT_ENCODING; - case 'g': - if (last) { - return 2; - } - goto ACCEPT_ENCODING; - default: - return -1; - } - -ACCEPT_L: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCEPT_LA; - case 'a': - if (last) { - return -1; - } - goto ACCEPT_LA; - default: - return -1; - } - -ACCEPT_LA: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto ACCEPT_LAN; - case 'n': - if (last) { - return -1; - } - goto ACCEPT_LAN; - default: - return -1; - } - -ACCEPT_LAN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto ACCEPT_LANG; - case 'g': - if (last) { - return -1; - } - goto ACCEPT_LANG; - default: - return -1; - } - -ACCEPT_LANG: - NEXT_CHAR(); - switch (ch) { - case 'U': - if (last) { - return -1; - } - goto ACCEPT_LANGU; - case 'u': - if (last) { - return -1; - } - goto ACCEPT_LANGU; - default: - return -1; - } - -ACCEPT_LANGU: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCEPT_LANGUA; - case 'a': - if (last) { - return -1; - } - goto ACCEPT_LANGUA; - default: - return -1; - } - -ACCEPT_LANGUA: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto ACCEPT_LANGUAG; - case 'g': - if (last) { - return -1; - } - goto ACCEPT_LANGUAG; - default: - return -1; - } - -ACCEPT_LANGUAG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 3; - } - goto ACCEPT_LANGUAGE; - case 'e': - if (last) { - return 3; - } - goto ACCEPT_LANGUAGE; - default: - return -1; - } - -ACCEPT_R: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCEPT_RA; - case 'a': - if (last) { - return -1; - } - goto ACCEPT_RA; - default: - return -1; - } - -ACCEPT_RA: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto ACCEPT_RAN; - case 'n': - if (last) { - return -1; - } - goto ACCEPT_RAN; - default: - return -1; - } - -ACCEPT_RAN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto ACCEPT_RANG; - case 'g': - if (last) { - return -1; - } - goto ACCEPT_RANG; - default: - return -1; - } - -ACCEPT_RANG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCEPT_RANGE; - case 'e': - if (last) { - return -1; - } - goto ACCEPT_RANGE; - default: - return -1; - } - -ACCEPT_RANGE: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return 4; - } - goto ACCEPT_RANGES; - case 's': - if (last) { - return 4; - } - goto ACCEPT_RANGES; - default: - return -1; - } - -ACCES: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto ACCESS; - case 's': - if (last) { - return -1; - } - goto ACCESS; - default: - return -1; - } - -ACCESS: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto ACCESS_; - default: - return -1; - } - -ACCESS_: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto ACCESS_C; - case 'c': - if (last) { - return -1; - } - goto ACCESS_C; - default: - return -1; - } - -ACCESS_C: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto ACCESS_CO; - case 'o': - if (last) { - return -1; - } - goto ACCESS_CO; - default: - return -1; - } - -ACCESS_CO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto ACCESS_CON; - case 'n': - if (last) { - return -1; - } - goto ACCESS_CON; - default: - return -1; - } - -ACCESS_CON: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto ACCESS_CONT; - case 't': - if (last) { - return -1; - } - goto ACCESS_CONT; - default: - return -1; - } - -ACCESS_CONT: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto ACCESS_CONTR; - case 'r': - if (last) { - return -1; - } - goto ACCESS_CONTR; - default: - return -1; - } - -ACCESS_CONTR: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto ACCESS_CONTRO; - case 'o': - if (last) { - return -1; - } - goto ACCESS_CONTRO; - default: - return -1; - } - -ACCESS_CONTRO: - NEXT_CHAR(); - switch (ch) { - case 'L': - if (last) { - return -1; - } - goto ACCESS_CONTROL; - case 'l': - if (last) { - return -1; - } - goto ACCESS_CONTROL; - default: - return -1; - } - -ACCESS_CONTROL: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto ACCESS_CONTROL_; - default: - return -1; - } - -ACCESS_CONTROL_: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCESS_CONTROL_A; - case 'a': - if (last) { - return -1; - } - goto ACCESS_CONTROL_A; - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_E; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_E; - case 'M': - if (last) { - return -1; - } - goto ACCESS_CONTROL_M; - case 'm': - if (last) { - return -1; - } - goto ACCESS_CONTROL_M; - case 'R': - if (last) { - return -1; - } - goto ACCESS_CONTROL_R; - case 'r': - if (last) { - return -1; - } - goto ACCESS_CONTROL_R; - default: - return -1; - } - -ACCESS_CONTROL_A: - NEXT_CHAR(); - switch (ch) { - case 'L': - if (last) { - return -1; - } - goto ACCESS_CONTROL_AL; - case 'l': - if (last) { - return -1; - } - goto ACCESS_CONTROL_AL; - default: - return -1; - } - -ACCESS_CONTROL_AL: - NEXT_CHAR(); - switch (ch) { - case 'L': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALL; - case 'l': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALL; - default: - return -1; - } - -ACCESS_CONTROL_ALL: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLO; - case 'o': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLO; - default: - return -1; - } - -ACCESS_CONTROL_ALLO: - NEXT_CHAR(); - switch (ch) { - case 'W': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW; - case 'w': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_C; - case 'c': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_C; - case 'H': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_H; - case 'h': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_H; - case 'M': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_M; - case 'm': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_M; - case 'O': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_O; - case 'o': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_O; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_C: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CR; - case 'r': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CR; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_CR: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CRE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CRE; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_CRE: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CRED; - case 'd': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CRED; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_CRED: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDE; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_CREDE: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDEN; - case 'n': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDEN; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_CREDEN: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDENT; - case 't': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDENT; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_CREDENT: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDENTI; - case 'i': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDENTI; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_CREDENTI: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDENTIA; - case 'a': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDENTIA; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_CREDENTIA: - NEXT_CHAR(); - switch (ch) { - case 'L': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDENTIAL; - case 'l': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_CREDENTIAL; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_CREDENTIAL: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return 5; - } - goto ACCESS_CONTROL_ALLOW_CREDENTIALS; - case 's': - if (last) { - return 5; - } - goto ACCESS_CONTROL_ALLOW_CREDENTIALS; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_H: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_HE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_HE; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_HE: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_HEA; - case 'a': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_HEA; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_HEA: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_HEAD; - case 'd': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_HEAD; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_HEAD: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_HEADE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_HEADE; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_HEADE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_HEADER; - case 'r': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_HEADER; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_HEADER: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return 6; - } - goto ACCESS_CONTROL_ALLOW_HEADERS; - case 's': - if (last) { - return 6; - } - goto ACCESS_CONTROL_ALLOW_HEADERS; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_M: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_ME; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_ME; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_ME: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_MET; - case 't': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_MET; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_MET: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_METH; - case 'h': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_METH; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_METH: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_METHO; - case 'o': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_METHO; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_METHO: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_METHOD; - case 'd': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_METHOD; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_METHOD: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return 7; - } - goto ACCESS_CONTROL_ALLOW_METHODS; - case 's': - if (last) { - return 7; - } - goto ACCESS_CONTROL_ALLOW_METHODS; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_O: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_OR; - case 'r': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_OR; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_OR: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_ORI; - case 'i': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_ORI; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_ORI: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_ORIG; - case 'g': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_ORIG; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_ORIG: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_ORIGI; - case 'i': - if (last) { - return -1; - } - goto ACCESS_CONTROL_ALLOW_ORIGI; - default: - return -1; - } - -ACCESS_CONTROL_ALLOW_ORIGI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return 8; - } - goto ACCESS_CONTROL_ALLOW_ORIGIN; - case 'n': - if (last) { - return 8; - } - goto ACCESS_CONTROL_ALLOW_ORIGIN; - default: - return -1; - } - -ACCESS_CONTROL_E: - NEXT_CHAR(); - switch (ch) { - case 'X': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EX; - case 'x': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EX; - default: - return -1; - } - -ACCESS_CONTROL_EX: - NEXT_CHAR(); - switch (ch) { - case 'P': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXP; - case 'p': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXP; - default: - return -1; - } - -ACCESS_CONTROL_EXP: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPO; - case 'o': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPO; - default: - return -1; - } - -ACCESS_CONTROL_EXPO: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOS; - case 's': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOS; - default: - return -1; - } - -ACCESS_CONTROL_EXPOS: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE; - default: - return -1; - } - -ACCESS_CONTROL_EXPOSE: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_; - default: - return -1; - } - -ACCESS_CONTROL_EXPOSE_: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_H; - case 'h': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_H; - default: - return -1; - } - -ACCESS_CONTROL_EXPOSE_H: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_HE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_HE; - default: - return -1; - } - -ACCESS_CONTROL_EXPOSE_HE: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_HEA; - case 'a': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_HEA; - default: - return -1; - } - -ACCESS_CONTROL_EXPOSE_HEA: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_HEAD; - case 'd': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_HEAD; - default: - return -1; - } - -ACCESS_CONTROL_EXPOSE_HEAD: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_HEADE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_HEADE; - default: - return -1; - } - -ACCESS_CONTROL_EXPOSE_HEADE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_HEADER; - case 'r': - if (last) { - return -1; - } - goto ACCESS_CONTROL_EXPOSE_HEADER; - default: - return -1; - } - -ACCESS_CONTROL_EXPOSE_HEADER: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return 9; - } - goto ACCESS_CONTROL_EXPOSE_HEADERS; - case 's': - if (last) { - return 9; - } - goto ACCESS_CONTROL_EXPOSE_HEADERS; - default: - return -1; - } - -ACCESS_CONTROL_M: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCESS_CONTROL_MA; - case 'a': - if (last) { - return -1; - } - goto ACCESS_CONTROL_MA; - default: - return -1; - } - -ACCESS_CONTROL_MA: - NEXT_CHAR(); - switch (ch) { - case 'X': - if (last) { - return -1; - } - goto ACCESS_CONTROL_MAX; - case 'x': - if (last) { - return -1; - } - goto ACCESS_CONTROL_MAX; - default: - return -1; - } - -ACCESS_CONTROL_MAX: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto ACCESS_CONTROL_MAX_; - default: - return -1; - } - -ACCESS_CONTROL_MAX_: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCESS_CONTROL_MAX_A; - case 'a': - if (last) { - return -1; - } - goto ACCESS_CONTROL_MAX_A; - default: - return -1; - } - -ACCESS_CONTROL_MAX_A: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto ACCESS_CONTROL_MAX_AG; - case 'g': - if (last) { - return -1; - } - goto ACCESS_CONTROL_MAX_AG; - default: - return -1; - } - -ACCESS_CONTROL_MAX_AG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 10; - } - goto ACCESS_CONTROL_MAX_AGE; - case 'e': - if (last) { - return 10; - } - goto ACCESS_CONTROL_MAX_AGE; - default: - return -1; - } - -ACCESS_CONTROL_R: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_RE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_RE; - default: - return -1; - } - -ACCESS_CONTROL_RE: - NEXT_CHAR(); - switch (ch) { - case 'Q': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQ; - case 'q': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQ; - default: - return -1; - } - -ACCESS_CONTROL_REQ: - NEXT_CHAR(); - switch (ch) { - case 'U': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQU; - case 'u': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQU; - default: - return -1; - } - -ACCESS_CONTROL_REQU: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUE; - default: - return -1; - } - -ACCESS_CONTROL_REQUE: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUES; - case 's': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUES; - default: - return -1; - } - -ACCESS_CONTROL_REQUES: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST; - case 't': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_H; - case 'h': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_H; - case 'M': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_M; - case 'm': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_M; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_H: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_HE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_HE; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_HE: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_HEA; - case 'a': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_HEA; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_HEA: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_HEAD; - case 'd': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_HEAD; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_HEAD: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_HEADE; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_HEADE; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_HEADE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_HEADER; - case 'r': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_HEADER; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_HEADER: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return 11; - } - goto ACCESS_CONTROL_REQUEST_HEADERS; - case 's': - if (last) { - return 11; - } - goto ACCESS_CONTROL_REQUEST_HEADERS; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_M: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_ME; - case 'e': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_ME; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_ME: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_MET; - case 't': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_MET; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_MET: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_METH; - case 'h': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_METH; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_METH: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_METHO; - case 'o': - if (last) { - return -1; - } - goto ACCESS_CONTROL_REQUEST_METHO; - default: - return -1; - } - -ACCESS_CONTROL_REQUEST_METHO: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return 12; - } - goto ACCESS_CONTROL_REQUEST_METHOD; - case 'd': - if (last) { - return 12; - } - goto ACCESS_CONTROL_REQUEST_METHOD; - default: - return -1; - } - -AG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 13; - } - goto AGE; - case 'e': - if (last) { - return 13; - } - goto AGE; - default: - return -1; - } - -AL: - NEXT_CHAR(); - switch (ch) { - case 'L': - if (last) { - return -1; - } - goto ALL; - case 'l': - if (last) { - return -1; - } - goto ALL; - default: - return -1; - } - -ALL: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto ALLO; - case 'o': - if (last) { - return -1; - } - goto ALLO; - default: - return -1; - } - -ALLO: - NEXT_CHAR(); - switch (ch) { - case 'W': - if (last) { - return 14; - } - goto ALLOW; - case 'w': - if (last) { - return 14; - } - goto ALLOW; - default: - return -1; - } - -AU: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto AUT; - case 't': - if (last) { - return -1; - } - goto AUT; - default: - return -1; - } - -AUT: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return -1; - } - goto AUTH; - case 'h': - if (last) { - return -1; - } - goto AUTH; - default: - return -1; - } - -AUTH: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto AUTHO; - case 'o': - if (last) { - return -1; - } - goto AUTHO; - default: - return -1; - } - -AUTHO: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto AUTHOR; - case 'r': - if (last) { - return -1; - } - goto AUTHOR; - default: - return -1; - } - -AUTHOR: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto AUTHORI; - case 'i': - if (last) { - return -1; - } - goto AUTHORI; - default: - return -1; - } - -AUTHORI: - NEXT_CHAR(); - switch (ch) { - case 'Z': - if (last) { - return -1; - } - goto AUTHORIZ; - case 'z': - if (last) { - return -1; - } - goto AUTHORIZ; - default: - return -1; - } - -AUTHORIZ: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto AUTHORIZA; - case 'a': - if (last) { - return -1; - } - goto AUTHORIZA; - default: - return -1; - } - -AUTHORIZA: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto AUTHORIZAT; - case 't': - if (last) { - return -1; - } - goto AUTHORIZAT; - default: - return -1; - } - -AUTHORIZAT: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto AUTHORIZATI; - case 'i': - if (last) { - return -1; - } - goto AUTHORIZATI; - default: - return -1; - } - -AUTHORIZATI: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto AUTHORIZATIO; - case 'o': - if (last) { - return -1; - } - goto AUTHORIZATIO; - default: - return -1; - } - -AUTHORIZATIO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return 15; - } - goto AUTHORIZATION; - case 'n': - if (last) { - return 15; - } - goto AUTHORIZATION; - default: - return -1; - } - -C: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto CA; - case 'a': - if (last) { - return -1; - } - goto CA; - case 'O': - if (last) { - return -1; - } - goto CO; - case 'o': - if (last) { - return -1; - } - goto CO; - default: - return -1; - } - -CA: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto CAC; - case 'c': - if (last) { - return -1; - } - goto CAC; - default: - return -1; - } - -CAC: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return -1; - } - goto CACH; - case 'h': - if (last) { - return -1; - } - goto CACH; - default: - return -1; - } - -CACH: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto CACHE; - case 'e': - if (last) { - return -1; - } - goto CACHE; - default: - return -1; - } - -CACHE: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto CACHE_; - default: - return -1; - } - -CACHE_: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto CACHE_C; - case 'c': - if (last) { - return -1; - } - goto CACHE_C; - default: - return -1; - } - -CACHE_C: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto CACHE_CO; - case 'o': - if (last) { - return -1; - } - goto CACHE_CO; - default: - return -1; - } - -CACHE_CO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CACHE_CON; - case 'n': - if (last) { - return -1; - } - goto CACHE_CON; - default: - return -1; - } - -CACHE_CON: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto CACHE_CONT; - case 't': - if (last) { - return -1; - } - goto CACHE_CONT; - default: - return -1; - } - -CACHE_CONT: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto CACHE_CONTR; - case 'r': - if (last) { - return -1; - } - goto CACHE_CONTR; - default: - return -1; - } - -CACHE_CONTR: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto CACHE_CONTRO; - case 'o': - if (last) { - return -1; - } - goto CACHE_CONTRO; - default: - return -1; - } - -CACHE_CONTRO: - NEXT_CHAR(); - switch (ch) { - case 'L': - if (last) { - return 16; - } - goto CACHE_CONTROL; - case 'l': - if (last) { - return 16; - } - goto CACHE_CONTROL; - default: - return -1; - } - -CO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CON; - case 'n': - if (last) { - return -1; - } - goto CON; - case 'O': - if (last) { - return -1; - } - goto COO; - case 'o': - if (last) { - return -1; - } - goto COO; - default: - return -1; - } - -CON: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CONN; - case 'n': - if (last) { - return -1; - } - goto CONN; - case 'T': - if (last) { - return -1; - } - goto CONT; - case 't': - if (last) { - return -1; - } - goto CONT; - default: - return -1; - } - -CONN: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto CONNE; - case 'e': - if (last) { - return -1; - } - goto CONNE; - default: - return -1; - } - -CONNE: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto CONNEC; - case 'c': - if (last) { - return -1; - } - goto CONNEC; - default: - return -1; - } - -CONNEC: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto CONNECT; - case 't': - if (last) { - return -1; - } - goto CONNECT; - default: - return -1; - } - -CONNECT: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto CONNECTI; - case 'i': - if (last) { - return -1; - } - goto CONNECTI; - default: - return -1; - } - -CONNECTI: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto CONNECTIO; - case 'o': - if (last) { - return -1; - } - goto CONNECTIO; - default: - return -1; - } - -CONNECTIO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return 17; - } - goto CONNECTION; - case 'n': - if (last) { - return 17; - } - goto CONNECTION; - default: - return -1; - } - -CONT: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto CONTE; - case 'e': - if (last) { - return -1; - } - goto CONTE; - default: - return -1; - } - -CONTE: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CONTEN; - case 'n': - if (last) { - return -1; - } - goto CONTEN; - default: - return -1; - } - -CONTEN: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto CONTENT; - case 't': - if (last) { - return -1; - } - goto CONTENT; - default: - return -1; - } - -CONTENT: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto CONTENT_; - default: - return -1; - } - -CONTENT_: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto CONTENT_D; - case 'd': - if (last) { - return -1; - } - goto CONTENT_D; - case 'E': - if (last) { - return -1; - } - goto CONTENT_E; - case 'e': - if (last) { - return -1; - } - goto CONTENT_E; - case 'L': - if (last) { - return -1; - } - goto CONTENT_L; - case 'l': - if (last) { - return -1; - } - goto CONTENT_L; - case 'M': - if (last) { - return -1; - } - goto CONTENT_M; - case 'm': - if (last) { - return -1; - } - goto CONTENT_M; - case 'R': - if (last) { - return -1; - } - goto CONTENT_R; - case 'r': - if (last) { - return -1; - } - goto CONTENT_R; - case 'T': - if (last) { - return -1; - } - goto CONTENT_T; - case 't': - if (last) { - return -1; - } - goto CONTENT_T; - default: - return -1; - } - -CONTENT_D: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto CONTENT_DI; - case 'i': - if (last) { - return -1; - } - goto CONTENT_DI; - default: - return -1; - } - -CONTENT_DI: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto CONTENT_DIS; - case 's': - if (last) { - return -1; - } - goto CONTENT_DIS; - default: - return -1; - } - -CONTENT_DIS: - NEXT_CHAR(); - switch (ch) { - case 'P': - if (last) { - return -1; - } - goto CONTENT_DISP; - case 'p': - if (last) { - return -1; - } - goto CONTENT_DISP; - default: - return -1; - } - -CONTENT_DISP: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto CONTENT_DISPO; - case 'o': - if (last) { - return -1; - } - goto CONTENT_DISPO; - default: - return -1; - } - -CONTENT_DISPO: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto CONTENT_DISPOS; - case 's': - if (last) { - return -1; - } - goto CONTENT_DISPOS; - default: - return -1; - } - -CONTENT_DISPOS: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto CONTENT_DISPOSI; - case 'i': - if (last) { - return -1; - } - goto CONTENT_DISPOSI; - default: - return -1; - } - -CONTENT_DISPOSI: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto CONTENT_DISPOSIT; - case 't': - if (last) { - return -1; - } - goto CONTENT_DISPOSIT; - default: - return -1; - } - -CONTENT_DISPOSIT: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto CONTENT_DISPOSITI; - case 'i': - if (last) { - return -1; - } - goto CONTENT_DISPOSITI; - default: - return -1; - } - -CONTENT_DISPOSITI: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto CONTENT_DISPOSITIO; - case 'o': - if (last) { - return -1; - } - goto CONTENT_DISPOSITIO; - default: - return -1; - } - -CONTENT_DISPOSITIO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return 18; - } - goto CONTENT_DISPOSITION; - case 'n': - if (last) { - return 18; - } - goto CONTENT_DISPOSITION; - default: - return -1; - } - -CONTENT_E: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CONTENT_EN; - case 'n': - if (last) { - return -1; - } - goto CONTENT_EN; - default: - return -1; - } - -CONTENT_EN: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto CONTENT_ENC; - case 'c': - if (last) { - return -1; - } - goto CONTENT_ENC; - default: - return -1; - } - -CONTENT_ENC: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto CONTENT_ENCO; - case 'o': - if (last) { - return -1; - } - goto CONTENT_ENCO; - default: - return -1; - } - -CONTENT_ENCO: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto CONTENT_ENCOD; - case 'd': - if (last) { - return -1; - } - goto CONTENT_ENCOD; - default: - return -1; - } - -CONTENT_ENCOD: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto CONTENT_ENCODI; - case 'i': - if (last) { - return -1; - } - goto CONTENT_ENCODI; - default: - return -1; - } - -CONTENT_ENCODI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CONTENT_ENCODIN; - case 'n': - if (last) { - return -1; - } - goto CONTENT_ENCODIN; - default: - return -1; - } - -CONTENT_ENCODIN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return 19; - } - goto CONTENT_ENCODING; - case 'g': - if (last) { - return 19; - } - goto CONTENT_ENCODING; - default: - return -1; - } - -CONTENT_L: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto CONTENT_LA; - case 'a': - if (last) { - return -1; - } - goto CONTENT_LA; - case 'E': - if (last) { - return -1; - } - goto CONTENT_LE; - case 'e': - if (last) { - return -1; - } - goto CONTENT_LE; - case 'O': - if (last) { - return -1; - } - goto CONTENT_LO; - case 'o': - if (last) { - return -1; - } - goto CONTENT_LO; - default: - return -1; - } - -CONTENT_LA: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CONTENT_LAN; - case 'n': - if (last) { - return -1; - } - goto CONTENT_LAN; - default: - return -1; - } - -CONTENT_LAN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto CONTENT_LANG; - case 'g': - if (last) { - return -1; - } - goto CONTENT_LANG; - default: - return -1; - } - -CONTENT_LANG: - NEXT_CHAR(); - switch (ch) { - case 'U': - if (last) { - return -1; - } - goto CONTENT_LANGU; - case 'u': - if (last) { - return -1; - } - goto CONTENT_LANGU; - default: - return -1; - } - -CONTENT_LANGU: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto CONTENT_LANGUA; - case 'a': - if (last) { - return -1; - } - goto CONTENT_LANGUA; - default: - return -1; - } - -CONTENT_LANGUA: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto CONTENT_LANGUAG; - case 'g': - if (last) { - return -1; - } - goto CONTENT_LANGUAG; - default: - return -1; - } - -CONTENT_LANGUAG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 20; - } - goto CONTENT_LANGUAGE; - case 'e': - if (last) { - return 20; - } - goto CONTENT_LANGUAGE; - default: - return -1; - } - -CONTENT_LE: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CONTENT_LEN; - case 'n': - if (last) { - return -1; - } - goto CONTENT_LEN; - default: - return -1; - } - -CONTENT_LEN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto CONTENT_LENG; - case 'g': - if (last) { - return -1; - } - goto CONTENT_LENG; - default: - return -1; - } - -CONTENT_LENG: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto CONTENT_LENGT; - case 't': - if (last) { - return -1; - } - goto CONTENT_LENGT; - default: - return -1; - } - -CONTENT_LENGT: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return 21; - } - goto CONTENT_LENGTH; - case 'h': - if (last) { - return 21; - } - goto CONTENT_LENGTH; - default: - return -1; - } - -CONTENT_LO: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto CONTENT_LOC; - case 'c': - if (last) { - return -1; - } - goto CONTENT_LOC; - default: - return -1; - } - -CONTENT_LOC: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto CONTENT_LOCA; - case 'a': - if (last) { - return -1; - } - goto CONTENT_LOCA; - default: - return -1; - } - -CONTENT_LOCA: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto CONTENT_LOCAT; - case 't': - if (last) { - return -1; - } - goto CONTENT_LOCAT; - default: - return -1; - } - -CONTENT_LOCAT: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto CONTENT_LOCATI; - case 'i': - if (last) { - return -1; - } - goto CONTENT_LOCATI; - default: - return -1; - } - -CONTENT_LOCATI: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto CONTENT_LOCATIO; - case 'o': - if (last) { - return -1; - } - goto CONTENT_LOCATIO; - default: - return -1; - } - -CONTENT_LOCATIO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return 22; - } - goto CONTENT_LOCATION; - case 'n': - if (last) { - return 22; - } - goto CONTENT_LOCATION; - default: - return -1; - } - -CONTENT_M: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto CONTENT_MD; - case 'd': - if (last) { - return -1; - } - goto CONTENT_MD; - default: - return -1; - } - -CONTENT_MD: - NEXT_CHAR(); - switch (ch) { - case '5': - if (last) { - return 23; - } - goto CONTENT_MD5; - default: - return -1; - } - -CONTENT_R: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto CONTENT_RA; - case 'a': - if (last) { - return -1; - } - goto CONTENT_RA; - default: - return -1; - } - -CONTENT_RA: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CONTENT_RAN; - case 'n': - if (last) { - return -1; - } - goto CONTENT_RAN; - default: - return -1; - } - -CONTENT_RAN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto CONTENT_RANG; - case 'g': - if (last) { - return -1; - } - goto CONTENT_RANG; - default: - return -1; - } - -CONTENT_RANG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 24; - } - goto CONTENT_RANGE; - case 'e': - if (last) { - return 24; - } - goto CONTENT_RANGE; - default: - return -1; - } - -CONTENT_T: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto CONTENT_TR; - case 'r': - if (last) { - return -1; - } - goto CONTENT_TR; - case 'Y': - if (last) { - return -1; - } - goto CONTENT_TY; - case 'y': - if (last) { - return -1; - } - goto CONTENT_TY; - default: - return -1; - } - -CONTENT_TR: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto CONTENT_TRA; - case 'a': - if (last) { - return -1; - } - goto CONTENT_TRA; - default: - return -1; - } - -CONTENT_TRA: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CONTENT_TRAN; - case 'n': - if (last) { - return -1; - } - goto CONTENT_TRAN; - default: - return -1; - } - -CONTENT_TRAN: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto CONTENT_TRANS; - case 's': - if (last) { - return -1; - } - goto CONTENT_TRANS; - default: - return -1; - } - -CONTENT_TRANS: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto CONTENT_TRANSF; - case 'f': - if (last) { - return -1; - } - goto CONTENT_TRANSF; - default: - return -1; - } - -CONTENT_TRANSF: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto CONTENT_TRANSFE; - case 'e': - if (last) { - return -1; - } - goto CONTENT_TRANSFE; - default: - return -1; - } - -CONTENT_TRANSFE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto CONTENT_TRANSFER; - case 'r': - if (last) { - return -1; - } - goto CONTENT_TRANSFER; - default: - return -1; - } - -CONTENT_TRANSFER: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_; - default: - return -1; - } - -CONTENT_TRANSFER_: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_E; - case 'e': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_E; - default: - return -1; - } - -CONTENT_TRANSFER_E: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_EN; - case 'n': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_EN; - default: - return -1; - } - -CONTENT_TRANSFER_EN: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_ENC; - case 'c': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_ENC; - default: - return -1; - } - -CONTENT_TRANSFER_ENC: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_ENCO; - case 'o': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_ENCO; - default: - return -1; - } - -CONTENT_TRANSFER_ENCO: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_ENCOD; - case 'd': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_ENCOD; - default: - return -1; - } - -CONTENT_TRANSFER_ENCOD: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_ENCODI; - case 'i': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_ENCODI; - default: - return -1; - } - -CONTENT_TRANSFER_ENCODI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_ENCODIN; - case 'n': - if (last) { - return -1; - } - goto CONTENT_TRANSFER_ENCODIN; - default: - return -1; - } - -CONTENT_TRANSFER_ENCODIN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return 25; - } - goto CONTENT_TRANSFER_ENCODING; - case 'g': - if (last) { - return 25; - } - goto CONTENT_TRANSFER_ENCODING; - default: - return -1; - } - -CONTENT_TY: - NEXT_CHAR(); - switch (ch) { - case 'P': - if (last) { - return -1; - } - goto CONTENT_TYP; - case 'p': - if (last) { - return -1; - } - goto CONTENT_TYP; - default: - return -1; - } - -CONTENT_TYP: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 26; - } - goto CONTENT_TYPE; - case 'e': - if (last) { - return 26; - } - goto CONTENT_TYPE; - default: - return -1; - } - -COO: - NEXT_CHAR(); - switch (ch) { - case 'K': - if (last) { - return -1; - } - goto COOK; - case 'k': - if (last) { - return -1; - } - goto COOK; - default: - return -1; - } - -COOK: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto COOKI; - case 'i': - if (last) { - return -1; - } - goto COOKI; - default: - return -1; - } - -COOKI: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 27; - } - goto COOKIE; - case 'e': - if (last) { - return 27; - } - goto COOKIE; - default: - return -1; - } - -D: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto DA; - case 'a': - if (last) { - return -1; - } - goto DA; - case 'E': - if (last) { - return -1; - } - goto DE; - case 'e': - if (last) { - return -1; - } - goto DE; - case 'I': - if (last) { - return -1; - } - goto DI; - case 'i': - if (last) { - return -1; - } - goto DI; - default: - return -1; - } - -DA: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto DAT; - case 't': - if (last) { - return -1; - } - goto DAT; - default: - return -1; - } - -DAT: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 28; - } - goto DATE; - case 'e': - if (last) { - return 28; - } - goto DATE; - default: - return -1; - } - -DE: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto DES; - case 's': - if (last) { - return -1; - } - goto DES; - default: - return -1; - } - -DES: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto DEST; - case 't': - if (last) { - return -1; - } - goto DEST; - default: - return -1; - } - -DEST: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto DESTI; - case 'i': - if (last) { - return -1; - } - goto DESTI; - default: - return -1; - } - -DESTI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto DESTIN; - case 'n': - if (last) { - return -1; - } - goto DESTIN; - default: - return -1; - } - -DESTIN: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto DESTINA; - case 'a': - if (last) { - return -1; - } - goto DESTINA; - default: - return -1; - } - -DESTINA: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto DESTINAT; - case 't': - if (last) { - return -1; - } - goto DESTINAT; - default: - return -1; - } - -DESTINAT: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto DESTINATI; - case 'i': - if (last) { - return -1; - } - goto DESTINATI; - default: - return -1; - } - -DESTINATI: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto DESTINATIO; - case 'o': - if (last) { - return -1; - } - goto DESTINATIO; - default: - return -1; - } - -DESTINATIO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return 29; - } - goto DESTINATION; - case 'n': - if (last) { - return 29; - } - goto DESTINATION; - default: - return -1; - } - -DI: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto DIG; - case 'g': - if (last) { - return -1; - } - goto DIG; - default: - return -1; - } - -DIG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto DIGE; - case 'e': - if (last) { - return -1; - } - goto DIGE; - default: - return -1; - } - -DIGE: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto DIGES; - case 's': - if (last) { - return -1; - } - goto DIGES; - default: - return -1; - } - -DIGES: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return 30; - } - goto DIGEST; - case 't': - if (last) { - return 30; - } - goto DIGEST; - default: - return -1; - } - -E: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto ET; - case 't': - if (last) { - return -1; - } - goto ET; - case 'X': - if (last) { - return -1; - } - goto EX; - case 'x': - if (last) { - return -1; - } - goto EX; - default: - return -1; - } - -ET: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto ETA; - case 'a': - if (last) { - return -1; - } - goto ETA; - default: - return -1; - } - -ETA: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return 31; - } - goto ETAG; - case 'g': - if (last) { - return 31; - } - goto ETAG; - default: - return -1; - } - -EX: - NEXT_CHAR(); - switch (ch) { - case 'P': - if (last) { - return -1; - } - goto EXP; - case 'p': - if (last) { - return -1; - } - goto EXP; - default: - return -1; - } - -EXP: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto EXPE; - case 'e': - if (last) { - return -1; - } - goto EXPE; - case 'I': - if (last) { - return -1; - } - goto EXPI; - case 'i': - if (last) { - return -1; - } - goto EXPI; - default: - return -1; - } - -EXPE: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto EXPEC; - case 'c': - if (last) { - return -1; - } - goto EXPEC; - default: - return -1; - } - -EXPEC: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return 32; - } - goto EXPECT; - case 't': - if (last) { - return 32; - } - goto EXPECT; - default: - return -1; - } - -EXPI: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto EXPIR; - case 'r': - if (last) { - return -1; - } - goto EXPIR; - default: - return -1; - } - -EXPIR: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto EXPIRE; - case 'e': - if (last) { - return -1; - } - goto EXPIRE; - default: - return -1; - } - -EXPIRE: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return 33; - } - goto EXPIRES; - case 's': - if (last) { - return 33; - } - goto EXPIRES; - default: - return -1; - } - -F: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto FO; - case 'o': - if (last) { - return -1; - } - goto FO; - case 'R': - if (last) { - return -1; - } - goto FR; - case 'r': - if (last) { - return -1; - } - goto FR; - default: - return -1; - } - -FO: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto FOR; - case 'r': - if (last) { - return -1; - } - goto FOR; - default: - return -1; - } - -FOR: - NEXT_CHAR(); - switch (ch) { - case 'W': - if (last) { - return -1; - } - goto FORW; - case 'w': - if (last) { - return -1; - } - goto FORW; - default: - return -1; - } - -FORW: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto FORWA; - case 'a': - if (last) { - return -1; - } - goto FORWA; - default: - return -1; - } - -FORWA: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto FORWAR; - case 'r': - if (last) { - return -1; - } - goto FORWAR; - default: - return -1; - } - -FORWAR: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto FORWARD; - case 'd': - if (last) { - return -1; - } - goto FORWARD; - default: - return -1; - } - -FORWARD: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto FORWARDE; - case 'e': - if (last) { - return -1; - } - goto FORWARDE; - default: - return -1; - } - -FORWARDE: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return 34; - } - goto FORWARDED; - case 'd': - if (last) { - return 34; - } - goto FORWARDED; - default: - return -1; - } - -FR: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto FRO; - case 'o': - if (last) { - return -1; - } - goto FRO; - default: - return -1; - } - -FRO: - NEXT_CHAR(); - switch (ch) { - case 'M': - if (last) { - return 35; - } - goto FROM; - case 'm': - if (last) { - return 35; - } - goto FROM; - default: - return -1; - } - -H: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto HO; - case 'o': - if (last) { - return -1; - } - goto HO; - default: - return -1; - } - -HO: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto HOS; - case 's': - if (last) { - return -1; - } - goto HOS; - default: - return -1; - } - -HOS: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return 36; - } - goto HOST; - case 't': - if (last) { - return 36; - } - goto HOST; - default: - return -1; - } - -I: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto IF; - case 'f': - if (last) { - return -1; - } - goto IF; - default: - return -1; - } - -IF: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto IF_; - default: - return -1; - } - -IF_: - NEXT_CHAR(); - switch (ch) { - case 'M': - if (last) { - return -1; - } - goto IF_M; - case 'm': - if (last) { - return -1; - } - goto IF_M; - case 'N': - if (last) { - return -1; - } - goto IF_N; - case 'n': - if (last) { - return -1; - } - goto IF_N; - case 'R': - if (last) { - return -1; - } - goto IF_R; - case 'r': - if (last) { - return -1; - } - goto IF_R; - case 'U': - if (last) { - return -1; - } - goto IF_U; - case 'u': - if (last) { - return -1; - } - goto IF_U; - default: - return -1; - } - -IF_M: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto IF_MA; - case 'a': - if (last) { - return -1; - } - goto IF_MA; - case 'O': - if (last) { - return -1; - } - goto IF_MO; - case 'o': - if (last) { - return -1; - } - goto IF_MO; - default: - return -1; - } - -IF_MA: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto IF_MAT; - case 't': - if (last) { - return -1; - } - goto IF_MAT; - default: - return -1; - } - -IF_MAT: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto IF_MATC; - case 'c': - if (last) { - return -1; - } - goto IF_MATC; - default: - return -1; - } - -IF_MATC: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return 37; - } - goto IF_MATCH; - case 'h': - if (last) { - return 37; - } - goto IF_MATCH; - default: - return -1; - } - -IF_MO: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto IF_MOD; - case 'd': - if (last) { - return -1; - } - goto IF_MOD; - default: - return -1; - } - -IF_MOD: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto IF_MODI; - case 'i': - if (last) { - return -1; - } - goto IF_MODI; - default: - return -1; - } - -IF_MODI: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto IF_MODIF; - case 'f': - if (last) { - return -1; - } - goto IF_MODIF; - default: - return -1; - } - -IF_MODIF: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto IF_MODIFI; - case 'i': - if (last) { - return -1; - } - goto IF_MODIFI; - default: - return -1; - } - -IF_MODIFI: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto IF_MODIFIE; - case 'e': - if (last) { - return -1; - } - goto IF_MODIFIE; - default: - return -1; - } - -IF_MODIFIE: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto IF_MODIFIED; - case 'd': - if (last) { - return -1; - } - goto IF_MODIFIED; - default: - return -1; - } - -IF_MODIFIED: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto IF_MODIFIED_; - default: - return -1; - } - -IF_MODIFIED_: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto IF_MODIFIED_S; - case 's': - if (last) { - return -1; - } - goto IF_MODIFIED_S; - default: - return -1; - } - -IF_MODIFIED_S: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto IF_MODIFIED_SI; - case 'i': - if (last) { - return -1; - } - goto IF_MODIFIED_SI; - default: - return -1; - } - -IF_MODIFIED_SI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto IF_MODIFIED_SIN; - case 'n': - if (last) { - return -1; - } - goto IF_MODIFIED_SIN; - default: - return -1; - } - -IF_MODIFIED_SIN: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto IF_MODIFIED_SINC; - case 'c': - if (last) { - return -1; - } - goto IF_MODIFIED_SINC; - default: - return -1; - } - -IF_MODIFIED_SINC: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 38; - } - goto IF_MODIFIED_SINCE; - case 'e': - if (last) { - return 38; - } - goto IF_MODIFIED_SINCE; - default: - return -1; - } - -IF_N: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto IF_NO; - case 'o': - if (last) { - return -1; - } - goto IF_NO; - default: - return -1; - } - -IF_NO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto IF_NON; - case 'n': - if (last) { - return -1; - } - goto IF_NON; - default: - return -1; - } - -IF_NON: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto IF_NONE; - case 'e': - if (last) { - return -1; - } - goto IF_NONE; - default: - return -1; - } - -IF_NONE: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto IF_NONE_; - default: - return -1; - } - -IF_NONE_: - NEXT_CHAR(); - switch (ch) { - case 'M': - if (last) { - return -1; - } - goto IF_NONE_M; - case 'm': - if (last) { - return -1; - } - goto IF_NONE_M; - default: - return -1; - } - -IF_NONE_M: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto IF_NONE_MA; - case 'a': - if (last) { - return -1; - } - goto IF_NONE_MA; - default: - return -1; - } - -IF_NONE_MA: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto IF_NONE_MAT; - case 't': - if (last) { - return -1; - } - goto IF_NONE_MAT; - default: - return -1; - } - -IF_NONE_MAT: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto IF_NONE_MATC; - case 'c': - if (last) { - return -1; - } - goto IF_NONE_MATC; - default: - return -1; - } - -IF_NONE_MATC: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return 39; - } - goto IF_NONE_MATCH; - case 'h': - if (last) { - return 39; - } - goto IF_NONE_MATCH; - default: - return -1; - } - -IF_R: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto IF_RA; - case 'a': - if (last) { - return -1; - } - goto IF_RA; - default: - return -1; - } - -IF_RA: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto IF_RAN; - case 'n': - if (last) { - return -1; - } - goto IF_RAN; - default: - return -1; - } - -IF_RAN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto IF_RANG; - case 'g': - if (last) { - return -1; - } - goto IF_RANG; - default: - return -1; - } - -IF_RANG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 40; - } - goto IF_RANGE; - case 'e': - if (last) { - return 40; - } - goto IF_RANGE; - default: - return -1; - } - -IF_U: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto IF_UN; - case 'n': - if (last) { - return -1; - } - goto IF_UN; - default: - return -1; - } - -IF_UN: - NEXT_CHAR(); - switch (ch) { - case 'M': - if (last) { - return -1; - } - goto IF_UNM; - case 'm': - if (last) { - return -1; - } - goto IF_UNM; - default: - return -1; - } - -IF_UNM: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto IF_UNMO; - case 'o': - if (last) { - return -1; - } - goto IF_UNMO; - default: - return -1; - } - -IF_UNMO: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto IF_UNMOD; - case 'd': - if (last) { - return -1; - } - goto IF_UNMOD; - default: - return -1; - } - -IF_UNMOD: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto IF_UNMODI; - case 'i': - if (last) { - return -1; - } - goto IF_UNMODI; - default: - return -1; - } - -IF_UNMODI: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto IF_UNMODIF; - case 'f': - if (last) { - return -1; - } - goto IF_UNMODIF; - default: - return -1; - } - -IF_UNMODIF: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto IF_UNMODIFI; - case 'i': - if (last) { - return -1; - } - goto IF_UNMODIFI; - default: - return -1; - } - -IF_UNMODIFI: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto IF_UNMODIFIE; - case 'e': - if (last) { - return -1; - } - goto IF_UNMODIFIE; - default: - return -1; - } - -IF_UNMODIFIE: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto IF_UNMODIFIED; - case 'd': - if (last) { - return -1; - } - goto IF_UNMODIFIED; - default: - return -1; - } - -IF_UNMODIFIED: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto IF_UNMODIFIED_; - default: - return -1; - } - -IF_UNMODIFIED_: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto IF_UNMODIFIED_S; - case 's': - if (last) { - return -1; - } - goto IF_UNMODIFIED_S; - default: - return -1; - } - -IF_UNMODIFIED_S: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto IF_UNMODIFIED_SI; - case 'i': - if (last) { - return -1; - } - goto IF_UNMODIFIED_SI; - default: - return -1; - } - -IF_UNMODIFIED_SI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto IF_UNMODIFIED_SIN; - case 'n': - if (last) { - return -1; - } - goto IF_UNMODIFIED_SIN; - default: - return -1; - } - -IF_UNMODIFIED_SIN: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto IF_UNMODIFIED_SINC; - case 'c': - if (last) { - return -1; - } - goto IF_UNMODIFIED_SINC; - default: - return -1; - } - -IF_UNMODIFIED_SINC: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 41; - } - goto IF_UNMODIFIED_SINCE; - case 'e': - if (last) { - return 41; - } - goto IF_UNMODIFIED_SINCE; - default: - return -1; - } - -K: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto KE; - case 'e': - if (last) { - return -1; - } - goto KE; - default: - return -1; - } - -KE: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto KEE; - case 'e': - if (last) { - return -1; - } - goto KEE; - default: - return -1; - } - -KEE: - NEXT_CHAR(); - switch (ch) { - case 'P': - if (last) { - return -1; - } - goto KEEP; - case 'p': - if (last) { - return -1; - } - goto KEEP; - default: - return -1; - } - -KEEP: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto KEEP_; - default: - return -1; - } - -KEEP_: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto KEEP_A; - case 'a': - if (last) { - return -1; - } - goto KEEP_A; - default: - return -1; - } - -KEEP_A: - NEXT_CHAR(); - switch (ch) { - case 'L': - if (last) { - return -1; - } - goto KEEP_AL; - case 'l': - if (last) { - return -1; - } - goto KEEP_AL; - default: - return -1; - } - -KEEP_AL: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto KEEP_ALI; - case 'i': - if (last) { - return -1; - } - goto KEEP_ALI; - default: - return -1; - } - -KEEP_ALI: - NEXT_CHAR(); - switch (ch) { - case 'V': - if (last) { - return -1; - } - goto KEEP_ALIV; - case 'v': - if (last) { - return -1; - } - goto KEEP_ALIV; - default: - return -1; - } - -KEEP_ALIV: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 42; - } - goto KEEP_ALIVE; - case 'e': - if (last) { - return 42; - } - goto KEEP_ALIVE; - default: - return -1; - } - -L: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto LA; - case 'a': - if (last) { - return -1; - } - goto LA; - case 'I': - if (last) { - return -1; - } - goto LI; - case 'i': - if (last) { - return -1; - } - goto LI; - case 'O': - if (last) { - return -1; - } - goto LO; - case 'o': - if (last) { - return -1; - } - goto LO; - default: - return -1; - } - -LA: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto LAS; - case 's': - if (last) { - return -1; - } - goto LAS; - default: - return -1; - } - -LAS: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto LAST; - case 't': - if (last) { - return -1; - } - goto LAST; - default: - return -1; - } - -LAST: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto LAST_; - default: - return -1; - } - -LAST_: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto LAST_E; - case 'e': - if (last) { - return -1; - } - goto LAST_E; - case 'M': - if (last) { - return -1; - } - goto LAST_M; - case 'm': - if (last) { - return -1; - } - goto LAST_M; - default: - return -1; - } - -LAST_E: - NEXT_CHAR(); - switch (ch) { - case 'V': - if (last) { - return -1; - } - goto LAST_EV; - case 'v': - if (last) { - return -1; - } - goto LAST_EV; - default: - return -1; - } - -LAST_EV: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto LAST_EVE; - case 'e': - if (last) { - return -1; - } - goto LAST_EVE; - default: - return -1; - } - -LAST_EVE: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto LAST_EVEN; - case 'n': - if (last) { - return -1; - } - goto LAST_EVEN; - default: - return -1; - } - -LAST_EVEN: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto LAST_EVENT; - case 't': - if (last) { - return -1; - } - goto LAST_EVENT; - default: - return -1; - } - -LAST_EVENT: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto LAST_EVENT_; - default: - return -1; - } - -LAST_EVENT_: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto LAST_EVENT_I; - case 'i': - if (last) { - return -1; - } - goto LAST_EVENT_I; - default: - return -1; - } - -LAST_EVENT_I: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return 43; - } - goto LAST_EVENT_ID; - case 'd': - if (last) { - return 43; - } - goto LAST_EVENT_ID; - default: - return -1; - } - -LAST_M: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto LAST_MO; - case 'o': - if (last) { - return -1; - } - goto LAST_MO; - default: - return -1; - } - -LAST_MO: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto LAST_MOD; - case 'd': - if (last) { - return -1; - } - goto LAST_MOD; - default: - return -1; - } - -LAST_MOD: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto LAST_MODI; - case 'i': - if (last) { - return -1; - } - goto LAST_MODI; - default: - return -1; - } - -LAST_MODI: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto LAST_MODIF; - case 'f': - if (last) { - return -1; - } - goto LAST_MODIF; - default: - return -1; - } - -LAST_MODIF: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto LAST_MODIFI; - case 'i': - if (last) { - return -1; - } - goto LAST_MODIFI; - default: - return -1; - } - -LAST_MODIFI: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto LAST_MODIFIE; - case 'e': - if (last) { - return -1; - } - goto LAST_MODIFIE; - default: - return -1; - } - -LAST_MODIFIE: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return 44; - } - goto LAST_MODIFIED; - case 'd': - if (last) { - return 44; - } - goto LAST_MODIFIED; - default: - return -1; - } - -LI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto LIN; - case 'n': - if (last) { - return -1; - } - goto LIN; - default: - return -1; - } - -LIN: - NEXT_CHAR(); - switch (ch) { - case 'K': - if (last) { - return 45; - } - goto LINK; - case 'k': - if (last) { - return 45; - } - goto LINK; - default: - return -1; - } - -LO: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto LOC; - case 'c': - if (last) { - return -1; - } - goto LOC; - default: - return -1; - } - -LOC: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto LOCA; - case 'a': - if (last) { - return -1; - } - goto LOCA; - default: - return -1; - } - -LOCA: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto LOCAT; - case 't': - if (last) { - return -1; - } - goto LOCAT; - default: - return -1; - } - -LOCAT: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto LOCATI; - case 'i': - if (last) { - return -1; - } - goto LOCATI; - default: - return -1; - } - -LOCATI: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto LOCATIO; - case 'o': - if (last) { - return -1; - } - goto LOCATIO; - default: - return -1; - } - -LOCATIO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return 46; - } - goto LOCATION; - case 'n': - if (last) { - return 46; - } - goto LOCATION; - default: - return -1; - } - -M: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto MA; - case 'a': - if (last) { - return -1; - } - goto MA; - default: - return -1; - } - -MA: - NEXT_CHAR(); - switch (ch) { - case 'X': - if (last) { - return -1; - } - goto MAX; - case 'x': - if (last) { - return -1; - } - goto MAX; - default: - return -1; - } - -MAX: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto MAX_; - default: - return -1; - } - -MAX_: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto MAX_F; - case 'f': - if (last) { - return -1; - } - goto MAX_F; - default: - return -1; - } - -MAX_F: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto MAX_FO; - case 'o': - if (last) { - return -1; - } - goto MAX_FO; - default: - return -1; - } - -MAX_FO: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto MAX_FOR; - case 'r': - if (last) { - return -1; - } - goto MAX_FOR; - default: - return -1; - } - -MAX_FOR: - NEXT_CHAR(); - switch (ch) { - case 'W': - if (last) { - return -1; - } - goto MAX_FORW; - case 'w': - if (last) { - return -1; - } - goto MAX_FORW; - default: - return -1; - } - -MAX_FORW: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto MAX_FORWA; - case 'a': - if (last) { - return -1; - } - goto MAX_FORWA; - default: - return -1; - } - -MAX_FORWA: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto MAX_FORWAR; - case 'r': - if (last) { - return -1; - } - goto MAX_FORWAR; - default: - return -1; - } - -MAX_FORWAR: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto MAX_FORWARD; - case 'd': - if (last) { - return -1; - } - goto MAX_FORWARD; - default: - return -1; - } - -MAX_FORWARD: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return 47; - } - goto MAX_FORWARDS; - case 's': - if (last) { - return 47; - } - goto MAX_FORWARDS; - default: - return -1; - } - -O: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto OR; - case 'r': - if (last) { - return -1; - } - goto OR; - default: - return -1; - } - -OR: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto ORI; - case 'i': - if (last) { - return -1; - } - goto ORI; - default: - return -1; - } - -ORI: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto ORIG; - case 'g': - if (last) { - return -1; - } - goto ORIG; - default: - return -1; - } - -ORIG: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto ORIGI; - case 'i': - if (last) { - return -1; - } - goto ORIGI; - default: - return -1; - } - -ORIGI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return 48; - } - goto ORIGIN; - case 'n': - if (last) { - return 48; - } - goto ORIGIN; - default: - return -1; - } - -P: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto PR; - case 'r': - if (last) { - return -1; - } - goto PR; - default: - return -1; - } - -PR: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto PRA; - case 'a': - if (last) { - return -1; - } - goto PRA; - case 'O': - if (last) { - return -1; - } - goto PRO; - case 'o': - if (last) { - return -1; - } - goto PRO; - default: - return -1; - } - -PRA: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto PRAG; - case 'g': - if (last) { - return -1; - } - goto PRAG; - default: - return -1; - } - -PRAG: - NEXT_CHAR(); - switch (ch) { - case 'M': - if (last) { - return -1; - } - goto PRAGM; - case 'm': - if (last) { - return -1; - } - goto PRAGM; - default: - return -1; - } - -PRAGM: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return 49; - } - goto PRAGMA; - case 'a': - if (last) { - return 49; - } - goto PRAGMA; - default: - return -1; - } - -PRO: - NEXT_CHAR(); - switch (ch) { - case 'X': - if (last) { - return -1; - } - goto PROX; - case 'x': - if (last) { - return -1; - } - goto PROX; - default: - return -1; - } - -PROX: - NEXT_CHAR(); - switch (ch) { - case 'Y': - if (last) { - return -1; - } - goto PROXY; - case 'y': - if (last) { - return -1; - } - goto PROXY; - default: - return -1; - } - -PROXY: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto PROXY_; - default: - return -1; - } - -PROXY_: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto PROXY_A; - case 'a': - if (last) { - return -1; - } - goto PROXY_A; - default: - return -1; - } - -PROXY_A: - NEXT_CHAR(); - switch (ch) { - case 'U': - if (last) { - return -1; - } - goto PROXY_AU; - case 'u': - if (last) { - return -1; - } - goto PROXY_AU; - default: - return -1; - } - -PROXY_AU: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto PROXY_AUT; - case 't': - if (last) { - return -1; - } - goto PROXY_AUT; - default: - return -1; - } - -PROXY_AUT: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return -1; - } - goto PROXY_AUTH; - case 'h': - if (last) { - return -1; - } - goto PROXY_AUTH; - default: - return -1; - } - -PROXY_AUTH: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto PROXY_AUTHE; - case 'e': - if (last) { - return -1; - } - goto PROXY_AUTHE; - case 'O': - if (last) { - return -1; - } - goto PROXY_AUTHO; - case 'o': - if (last) { - return -1; - } - goto PROXY_AUTHO; - default: - return -1; - } - -PROXY_AUTHE: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto PROXY_AUTHEN; - case 'n': - if (last) { - return -1; - } - goto PROXY_AUTHEN; - default: - return -1; - } - -PROXY_AUTHEN: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto PROXY_AUTHENT; - case 't': - if (last) { - return -1; - } - goto PROXY_AUTHENT; - default: - return -1; - } - -PROXY_AUTHENT: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto PROXY_AUTHENTI; - case 'i': - if (last) { - return -1; - } - goto PROXY_AUTHENTI; - default: - return -1; - } - -PROXY_AUTHENTI: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto PROXY_AUTHENTIC; - case 'c': - if (last) { - return -1; - } - goto PROXY_AUTHENTIC; - default: - return -1; - } - -PROXY_AUTHENTIC: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto PROXY_AUTHENTICA; - case 'a': - if (last) { - return -1; - } - goto PROXY_AUTHENTICA; - default: - return -1; - } - -PROXY_AUTHENTICA: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto PROXY_AUTHENTICAT; - case 't': - if (last) { - return -1; - } - goto PROXY_AUTHENTICAT; - default: - return -1; - } - -PROXY_AUTHENTICAT: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 50; - } - goto PROXY_AUTHENTICATE; - case 'e': - if (last) { - return 50; - } - goto PROXY_AUTHENTICATE; - default: - return -1; - } - -PROXY_AUTHO: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto PROXY_AUTHOR; - case 'r': - if (last) { - return -1; - } - goto PROXY_AUTHOR; - default: - return -1; - } - -PROXY_AUTHOR: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto PROXY_AUTHORI; - case 'i': - if (last) { - return -1; - } - goto PROXY_AUTHORI; - default: - return -1; - } - -PROXY_AUTHORI: - NEXT_CHAR(); - switch (ch) { - case 'Z': - if (last) { - return -1; - } - goto PROXY_AUTHORIZ; - case 'z': - if (last) { - return -1; - } - goto PROXY_AUTHORIZ; - default: - return -1; - } - -PROXY_AUTHORIZ: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto PROXY_AUTHORIZA; - case 'a': - if (last) { - return -1; - } - goto PROXY_AUTHORIZA; - default: - return -1; - } - -PROXY_AUTHORIZA: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto PROXY_AUTHORIZAT; - case 't': - if (last) { - return -1; - } - goto PROXY_AUTHORIZAT; - default: - return -1; - } - -PROXY_AUTHORIZAT: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto PROXY_AUTHORIZATI; - case 'i': - if (last) { - return -1; - } - goto PROXY_AUTHORIZATI; - default: - return -1; - } - -PROXY_AUTHORIZATI: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto PROXY_AUTHORIZATIO; - case 'o': - if (last) { - return -1; - } - goto PROXY_AUTHORIZATIO; - default: - return -1; - } - -PROXY_AUTHORIZATIO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return 51; - } - goto PROXY_AUTHORIZATION; - case 'n': - if (last) { - return 51; - } - goto PROXY_AUTHORIZATION; - default: - return -1; - } - -R: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto RA; - case 'a': - if (last) { - return -1; - } - goto RA; - case 'E': - if (last) { - return -1; - } - goto RE; - case 'e': - if (last) { - return -1; - } - goto RE; - default: - return -1; - } - -RA: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto RAN; - case 'n': - if (last) { - return -1; - } - goto RAN; - default: - return -1; - } - -RAN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto RANG; - case 'g': - if (last) { - return -1; - } - goto RANG; - default: - return -1; - } - -RANG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 52; - } - goto RANGE; - case 'e': - if (last) { - return 52; - } - goto RANGE; - default: - return -1; - } - -RE: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto REF; - case 'f': - if (last) { - return -1; - } - goto REF; - case 'T': - if (last) { - return -1; - } - goto RET; - case 't': - if (last) { - return -1; - } - goto RET; - default: - return -1; - } - -REF: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto REFE; - case 'e': - if (last) { - return -1; - } - goto REFE; - default: - return -1; - } - -REFE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto REFER; - case 'r': - if (last) { - return -1; - } - goto REFER; - default: - return -1; - } - -REFER: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto REFERE; - case 'e': - if (last) { - return -1; - } - goto REFERE; - default: - return -1; - } - -REFERE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return 53; - } - goto REFERER; - case 'r': - if (last) { - return 53; - } - goto REFERER; - default: - return -1; - } - -RET: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto RETR; - case 'r': - if (last) { - return -1; - } - goto RETR; - default: - return -1; - } - -RETR: - NEXT_CHAR(); - switch (ch) { - case 'Y': - if (last) { - return -1; - } - goto RETRY; - case 'y': - if (last) { - return -1; - } - goto RETRY; - default: - return -1; - } - -RETRY: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto RETRY_; - default: - return -1; - } - -RETRY_: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto RETRY_A; - case 'a': - if (last) { - return -1; - } - goto RETRY_A; - default: - return -1; - } - -RETRY_A: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto RETRY_AF; - case 'f': - if (last) { - return -1; - } - goto RETRY_AF; - default: - return -1; - } - -RETRY_AF: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto RETRY_AFT; - case 't': - if (last) { - return -1; - } - goto RETRY_AFT; - default: - return -1; - } - -RETRY_AFT: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto RETRY_AFTE; - case 'e': - if (last) { - return -1; - } - goto RETRY_AFTE; - default: - return -1; - } - -RETRY_AFTE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return 54; - } - goto RETRY_AFTER; - case 'r': - if (last) { - return 54; - } - goto RETRY_AFTER; - default: - return -1; - } - -S: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto SE; - case 'e': - if (last) { - return -1; - } - goto SE; - default: - return -1; - } - -SE: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto SEC; - case 'c': - if (last) { - return -1; - } - goto SEC; - case 'R': - if (last) { - return -1; - } - goto SER; - case 'r': - if (last) { - return -1; - } - goto SER; - case 'T': - if (last) { - return -1; - } - goto SET; - case 't': - if (last) { - return -1; - } - goto SET; - default: - return -1; - } - -SEC: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto SEC_; - default: - return -1; - } - -SEC_: - NEXT_CHAR(); - switch (ch) { - case 'W': - if (last) { - return -1; - } - goto SEC_W; - case 'w': - if (last) { - return -1; - } - goto SEC_W; - default: - return -1; - } - -SEC_W: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto SEC_WE; - case 'e': - if (last) { - return -1; - } - goto SEC_WE; - default: - return -1; - } - -SEC_WE: - NEXT_CHAR(); - switch (ch) { - case 'B': - if (last) { - return -1; - } - goto SEC_WEB; - case 'b': - if (last) { - return -1; - } - goto SEC_WEB; - default: - return -1; - } - -SEC_WEB: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto SEC_WEBS; - case 's': - if (last) { - return -1; - } - goto SEC_WEBS; - default: - return -1; - } - -SEC_WEBS: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto SEC_WEBSO; - case 'o': - if (last) { - return -1; - } - goto SEC_WEBSO; - default: - return -1; - } - -SEC_WEBSO: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto SEC_WEBSOC; - case 'c': - if (last) { - return -1; - } - goto SEC_WEBSOC; - default: - return -1; - } - -SEC_WEBSOC: - NEXT_CHAR(); - switch (ch) { - case 'K': - if (last) { - return -1; - } - goto SEC_WEBSOCK; - case 'k': - if (last) { - return -1; - } - goto SEC_WEBSOCK; - default: - return -1; - } - -SEC_WEBSOCK: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto SEC_WEBSOCKE; - case 'e': - if (last) { - return -1; - } - goto SEC_WEBSOCKE; - default: - return -1; - } - -SEC_WEBSOCKE: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto SEC_WEBSOCKET; - case 't': - if (last) { - return -1; - } - goto SEC_WEBSOCKET; - default: - return -1; - } - -SEC_WEBSOCKET: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_; - default: - return -1; - } - -SEC_WEBSOCKET_: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_A; - case 'a': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_A; - case 'E': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_E; - case 'e': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_E; - case 'K': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_K; - case 'k': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_K; - case 'P': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_P; - case 'p': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_P; - case 'V': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_V; - case 'v': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_V; - default: - return -1; - } - -SEC_WEBSOCKET_A: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_AC; - case 'c': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_AC; - default: - return -1; - } - -SEC_WEBSOCKET_AC: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_ACC; - case 'c': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_ACC; - default: - return -1; - } - -SEC_WEBSOCKET_ACC: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_ACCE; - case 'e': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_ACCE; - default: - return -1; - } - -SEC_WEBSOCKET_ACCE: - NEXT_CHAR(); - switch (ch) { - case 'P': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_ACCEP; - case 'p': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_ACCEP; - default: - return -1; - } - -SEC_WEBSOCKET_ACCEP: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return 55; - } - goto SEC_WEBSOCKET_ACCEPT; - case 't': - if (last) { - return 55; - } - goto SEC_WEBSOCKET_ACCEPT; - default: - return -1; - } - -SEC_WEBSOCKET_E: - NEXT_CHAR(); - switch (ch) { - case 'X': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EX; - case 'x': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EX; - default: - return -1; - } - -SEC_WEBSOCKET_EX: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXT; - case 't': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXT; - default: - return -1; - } - -SEC_WEBSOCKET_EXT: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTE; - case 'e': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTE; - default: - return -1; - } - -SEC_WEBSOCKET_EXTE: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTEN; - case 'n': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTEN; - default: - return -1; - } - -SEC_WEBSOCKET_EXTEN: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTENS; - case 's': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTENS; - default: - return -1; - } - -SEC_WEBSOCKET_EXTENS: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTENSI; - case 'i': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTENSI; - default: - return -1; - } - -SEC_WEBSOCKET_EXTENSI: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTENSIO; - case 'o': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTENSIO; - default: - return -1; - } - -SEC_WEBSOCKET_EXTENSIO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTENSION; - case 'n': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_EXTENSION; - default: - return -1; - } - -SEC_WEBSOCKET_EXTENSION: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return 56; - } - goto SEC_WEBSOCKET_EXTENSIONS; - case 's': - if (last) { - return 56; - } - goto SEC_WEBSOCKET_EXTENSIONS; - default: - return -1; - } - -SEC_WEBSOCKET_K: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_KE; - case 'e': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_KE; - default: - return -1; - } - -SEC_WEBSOCKET_KE: - NEXT_CHAR(); - switch (ch) { - case 'Y': - if (last) { - return 57; - } - goto SEC_WEBSOCKET_KEY; - case 'y': - if (last) { - return 57; - } - goto SEC_WEBSOCKET_KEY; - default: - return -1; - } - -SEC_WEBSOCKET_KEY: - NEXT_CHAR(); - switch (ch) { - case '1': - if (last) { - return 58; - } - goto SEC_WEBSOCKET_KEY1; - default: - return -1; - } - -SEC_WEBSOCKET_P: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PR; - case 'r': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PR; - default: - return -1; - } - -SEC_WEBSOCKET_PR: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PRO; - case 'o': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PRO; - default: - return -1; - } - -SEC_WEBSOCKET_PRO: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PROT; - case 't': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PROT; - default: - return -1; - } - -SEC_WEBSOCKET_PROT: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PROTO; - case 'o': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PROTO; - default: - return -1; - } - -SEC_WEBSOCKET_PROTO: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PROTOC; - case 'c': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PROTOC; - default: - return -1; - } - -SEC_WEBSOCKET_PROTOC: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PROTOCO; - case 'o': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_PROTOCO; - default: - return -1; - } - -SEC_WEBSOCKET_PROTOCO: - NEXT_CHAR(); - switch (ch) { - case 'L': - if (last) { - return 59; - } - goto SEC_WEBSOCKET_PROTOCOL; - case 'l': - if (last) { - return 59; - } - goto SEC_WEBSOCKET_PROTOCOL; - default: - return -1; - } - -SEC_WEBSOCKET_V: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_VE; - case 'e': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_VE; - default: - return -1; - } - -SEC_WEBSOCKET_VE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_VER; - case 'r': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_VER; - default: - return -1; - } - -SEC_WEBSOCKET_VER: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_VERS; - case 's': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_VERS; - default: - return -1; - } - -SEC_WEBSOCKET_VERS: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_VERSI; - case 'i': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_VERSI; - default: - return -1; - } - -SEC_WEBSOCKET_VERSI: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_VERSIO; - case 'o': - if (last) { - return -1; - } - goto SEC_WEBSOCKET_VERSIO; - default: - return -1; - } - -SEC_WEBSOCKET_VERSIO: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return 60; - } - goto SEC_WEBSOCKET_VERSION; - case 'n': - if (last) { - return 60; - } - goto SEC_WEBSOCKET_VERSION; - default: - return -1; - } - -SER: - NEXT_CHAR(); - switch (ch) { - case 'V': - if (last) { - return -1; - } - goto SERV; - case 'v': - if (last) { - return -1; - } - goto SERV; - default: - return -1; - } - -SERV: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto SERVE; - case 'e': - if (last) { - return -1; - } - goto SERVE; - default: - return -1; - } - -SERVE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return 61; - } - goto SERVER; - case 'r': - if (last) { - return 61; - } - goto SERVER; - default: - return -1; - } - -SET: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto SET_; - default: - return -1; - } - -SET_: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto SET_C; - case 'c': - if (last) { - return -1; - } - goto SET_C; - default: - return -1; - } - -SET_C: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto SET_CO; - case 'o': - if (last) { - return -1; - } - goto SET_CO; - default: - return -1; - } - -SET_CO: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto SET_COO; - case 'o': - if (last) { - return -1; - } - goto SET_COO; - default: - return -1; - } - -SET_COO: - NEXT_CHAR(); - switch (ch) { - case 'K': - if (last) { - return -1; - } - goto SET_COOK; - case 'k': - if (last) { - return -1; - } - goto SET_COOK; - default: - return -1; - } - -SET_COOK: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto SET_COOKI; - case 'i': - if (last) { - return -1; - } - goto SET_COOKI; - default: - return -1; - } - -SET_COOKI: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 62; - } - goto SET_COOKIE; - case 'e': - if (last) { - return 62; - } - goto SET_COOKIE; - default: - return -1; - } - -T: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 63; - } - goto TE; - case 'e': - if (last) { - return 63; - } - goto TE; - case 'R': - if (last) { - return -1; - } - goto TR; - case 'r': - if (last) { - return -1; - } - goto TR; - default: - return -1; - } - -TR: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto TRA; - case 'a': - if (last) { - return -1; - } - goto TRA; - default: - return -1; - } - -TRA: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto TRAI; - case 'i': - if (last) { - return -1; - } - goto TRAI; - case 'N': - if (last) { - return -1; - } - goto TRAN; - case 'n': - if (last) { - return -1; - } - goto TRAN; - default: - return -1; - } - -TRAI: - NEXT_CHAR(); - switch (ch) { - case 'L': - if (last) { - return -1; - } - goto TRAIL; - case 'l': - if (last) { - return -1; - } - goto TRAIL; - default: - return -1; - } - -TRAIL: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto TRAILE; - case 'e': - if (last) { - return -1; - } - goto TRAILE; - default: - return -1; - } - -TRAILE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return 64; - } - goto TRAILER; - case 'r': - if (last) { - return 64; - } - goto TRAILER; - default: - return -1; - } - -TRAN: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto TRANS; - case 's': - if (last) { - return -1; - } - goto TRANS; - default: - return -1; - } - -TRANS: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto TRANSF; - case 'f': - if (last) { - return -1; - } - goto TRANSF; - default: - return -1; - } - -TRANSF: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto TRANSFE; - case 'e': - if (last) { - return -1; - } - goto TRANSFE; - default: - return -1; - } - -TRANSFE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto TRANSFER; - case 'r': - if (last) { - return -1; - } - goto TRANSFER; - default: - return -1; - } - -TRANSFER: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto TRANSFER_; - default: - return -1; - } - -TRANSFER_: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto TRANSFER_E; - case 'e': - if (last) { - return -1; - } - goto TRANSFER_E; - default: - return -1; - } - -TRANSFER_E: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto TRANSFER_EN; - case 'n': - if (last) { - return -1; - } - goto TRANSFER_EN; - default: - return -1; - } - -TRANSFER_EN: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto TRANSFER_ENC; - case 'c': - if (last) { - return -1; - } - goto TRANSFER_ENC; - default: - return -1; - } - -TRANSFER_ENC: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto TRANSFER_ENCO; - case 'o': - if (last) { - return -1; - } - goto TRANSFER_ENCO; - default: - return -1; - } - -TRANSFER_ENCO: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto TRANSFER_ENCOD; - case 'd': - if (last) { - return -1; - } - goto TRANSFER_ENCOD; - default: - return -1; - } - -TRANSFER_ENCOD: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto TRANSFER_ENCODI; - case 'i': - if (last) { - return -1; - } - goto TRANSFER_ENCODI; - default: - return -1; - } - -TRANSFER_ENCODI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto TRANSFER_ENCODIN; - case 'n': - if (last) { - return -1; - } - goto TRANSFER_ENCODIN; - default: - return -1; - } - -TRANSFER_ENCODIN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return 65; - } - goto TRANSFER_ENCODING; - case 'g': - if (last) { - return 65; - } - goto TRANSFER_ENCODING; - default: - return -1; - } - -U: - NEXT_CHAR(); - switch (ch) { - case 'P': - if (last) { - return -1; - } - goto UP; - case 'p': - if (last) { - return -1; - } - goto UP; - case 'R': - if (last) { - return -1; - } - goto UR; - case 'r': - if (last) { - return -1; - } - goto UR; - case 'S': - if (last) { - return -1; - } - goto US; - case 's': - if (last) { - return -1; - } - goto US; - default: - return -1; - } - -UP: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto UPG; - case 'g': - if (last) { - return -1; - } - goto UPG; - default: - return -1; - } - -UPG: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto UPGR; - case 'r': - if (last) { - return -1; - } - goto UPGR; - default: - return -1; - } - -UPGR: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto UPGRA; - case 'a': - if (last) { - return -1; - } - goto UPGRA; - default: - return -1; - } - -UPGRA: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto UPGRAD; - case 'd': - if (last) { - return -1; - } - goto UPGRAD; - default: - return -1; - } - -UPGRAD: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 66; - } - goto UPGRADE; - case 'e': - if (last) { - return 66; - } - goto UPGRADE; - default: - return -1; - } - -UR: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return 67; - } - goto URI; - case 'i': - if (last) { - return 67; - } - goto URI; - default: - return -1; - } - -US: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto USE; - case 'e': - if (last) { - return -1; - } - goto USE; - default: - return -1; - } - -USE: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto USER; - case 'r': - if (last) { - return -1; - } - goto USER; - default: - return -1; - } - -USER: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto USER_; - default: - return -1; - } - -USER_: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto USER_A; - case 'a': - if (last) { - return -1; - } - goto USER_A; - default: - return -1; - } - -USER_A: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto USER_AG; - case 'g': - if (last) { - return -1; - } - goto USER_AG; - default: - return -1; - } - -USER_AG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto USER_AGE; - case 'e': - if (last) { - return -1; - } - goto USER_AGE; - default: - return -1; - } - -USER_AGE: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto USER_AGEN; - case 'n': - if (last) { - return -1; - } - goto USER_AGEN; - default: - return -1; - } - -USER_AGEN: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return 68; - } - goto USER_AGENT; - case 't': - if (last) { - return 68; - } - goto USER_AGENT; - default: - return -1; - } - -V: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto VA; - case 'a': - if (last) { - return -1; - } - goto VA; - case 'I': - if (last) { - return -1; - } - goto VI; - case 'i': - if (last) { - return -1; - } - goto VI; - default: - return -1; - } - -VA: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto VAR; - case 'r': - if (last) { - return -1; - } - goto VAR; - default: - return -1; - } - -VAR: - NEXT_CHAR(); - switch (ch) { - case 'Y': - if (last) { - return 69; - } - goto VARY; - case 'y': - if (last) { - return 69; - } - goto VARY; - default: - return -1; - } - -VI: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return 70; - } - goto VIA; - case 'a': - if (last) { - return 70; - } - goto VIA; - default: - return -1; - } - -W: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto WA; - case 'a': - if (last) { - return -1; - } - goto WA; - case 'E': - if (last) { - return -1; - } - goto WE; - case 'e': - if (last) { - return -1; - } - goto WE; - case 'W': - if (last) { - return -1; - } - goto WW; - case 'w': - if (last) { - return -1; - } - goto WW; - default: - return -1; - } - -WA: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto WAN; - case 'n': - if (last) { - return -1; - } - goto WAN; - case 'R': - if (last) { - return -1; - } - goto WAR; - case 'r': - if (last) { - return -1; - } - goto WAR; - default: - return -1; - } - -WAN: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto WANT; - case 't': - if (last) { - return -1; - } - goto WANT; - default: - return -1; - } - -WANT: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto WANT_; - default: - return -1; - } - -WANT_: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto WANT_D; - case 'd': - if (last) { - return -1; - } - goto WANT_D; - default: - return -1; - } - -WANT_D: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto WANT_DI; - case 'i': - if (last) { - return -1; - } - goto WANT_DI; - default: - return -1; - } - -WANT_DI: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return -1; - } - goto WANT_DIG; - case 'g': - if (last) { - return -1; - } - goto WANT_DIG; - default: - return -1; - } - -WANT_DIG: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto WANT_DIGE; - case 'e': - if (last) { - return -1; - } - goto WANT_DIGE; - default: - return -1; - } - -WANT_DIGE: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto WANT_DIGES; - case 's': - if (last) { - return -1; - } - goto WANT_DIGES; - default: - return -1; - } - -WANT_DIGES: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return 71; - } - goto WANT_DIGEST; - case 't': - if (last) { - return 71; - } - goto WANT_DIGEST; - default: - return -1; - } - -WAR: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto WARN; - case 'n': - if (last) { - return -1; - } - goto WARN; - default: - return -1; - } - -WARN: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto WARNI; - case 'i': - if (last) { - return -1; - } - goto WARNI; - default: - return -1; - } - -WARNI: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto WARNIN; - case 'n': - if (last) { - return -1; - } - goto WARNIN; - default: - return -1; - } - -WARNIN: - NEXT_CHAR(); - switch (ch) { - case 'G': - if (last) { - return 72; - } - goto WARNING; - case 'g': - if (last) { - return 72; - } - goto WARNING; - default: - return -1; - } - -WE: - NEXT_CHAR(); - switch (ch) { - case 'B': - if (last) { - return -1; - } - goto WEB; - case 'b': - if (last) { - return -1; - } - goto WEB; - default: - return -1; - } - -WEB: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto WEBS; - case 's': - if (last) { - return -1; - } - goto WEBS; - default: - return -1; - } - -WEBS: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto WEBSO; - case 'o': - if (last) { - return -1; - } - goto WEBSO; - default: - return -1; - } - -WEBSO: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto WEBSOC; - case 'c': - if (last) { - return -1; - } - goto WEBSOC; - default: - return -1; - } - -WEBSOC: - NEXT_CHAR(); - switch (ch) { - case 'K': - if (last) { - return -1; - } - goto WEBSOCK; - case 'k': - if (last) { - return -1; - } - goto WEBSOCK; - default: - return -1; - } - -WEBSOCK: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto WEBSOCKE; - case 'e': - if (last) { - return -1; - } - goto WEBSOCKE; - default: - return -1; - } - -WEBSOCKE: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return 73; - } - goto WEBSOCKET; - case 't': - if (last) { - return 73; - } - goto WEBSOCKET; - default: - return -1; - } - -WW: - NEXT_CHAR(); - switch (ch) { - case 'W': - if (last) { - return -1; - } - goto WWW; - case 'w': - if (last) { - return -1; - } - goto WWW; - default: - return -1; - } - -WWW: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto WWW_; - default: - return -1; - } - -WWW_: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto WWW_A; - case 'a': - if (last) { - return -1; - } - goto WWW_A; - default: - return -1; - } - -WWW_A: - NEXT_CHAR(); - switch (ch) { - case 'U': - if (last) { - return -1; - } - goto WWW_AU; - case 'u': - if (last) { - return -1; - } - goto WWW_AU; - default: - return -1; - } - -WWW_AU: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto WWW_AUT; - case 't': - if (last) { - return -1; - } - goto WWW_AUT; - default: - return -1; - } - -WWW_AUT: - NEXT_CHAR(); - switch (ch) { - case 'H': - if (last) { - return -1; - } - goto WWW_AUTH; - case 'h': - if (last) { - return -1; - } - goto WWW_AUTH; - default: - return -1; - } - -WWW_AUTH: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto WWW_AUTHE; - case 'e': - if (last) { - return -1; - } - goto WWW_AUTHE; - default: - return -1; - } - -WWW_AUTHE: - NEXT_CHAR(); - switch (ch) { - case 'N': - if (last) { - return -1; - } - goto WWW_AUTHEN; - case 'n': - if (last) { - return -1; - } - goto WWW_AUTHEN; - default: - return -1; - } - -WWW_AUTHEN: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto WWW_AUTHENT; - case 't': - if (last) { - return -1; - } - goto WWW_AUTHENT; - default: - return -1; - } - -WWW_AUTHENT: - NEXT_CHAR(); - switch (ch) { - case 'I': - if (last) { - return -1; - } - goto WWW_AUTHENTI; - case 'i': - if (last) { - return -1; - } - goto WWW_AUTHENTI; - default: - return -1; - } - -WWW_AUTHENTI: - NEXT_CHAR(); - switch (ch) { - case 'C': - if (last) { - return -1; - } - goto WWW_AUTHENTIC; - case 'c': - if (last) { - return -1; - } - goto WWW_AUTHENTIC; - default: - return -1; - } - -WWW_AUTHENTIC: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto WWW_AUTHENTICA; - case 'a': - if (last) { - return -1; - } - goto WWW_AUTHENTICA; - default: - return -1; - } - -WWW_AUTHENTICA: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto WWW_AUTHENTICAT; - case 't': - if (last) { - return -1; - } - goto WWW_AUTHENTICAT; - default: - return -1; - } - -WWW_AUTHENTICAT: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return 74; - } - goto WWW_AUTHENTICATE; - case 'e': - if (last) { - return 74; - } - goto WWW_AUTHENTICATE; - default: - return -1; - } - -X: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto X_; - default: - return -1; - } - -X_: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto X_F; - case 'f': - if (last) { - return -1; - } - goto X_F; - default: - return -1; - } - -X_F: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto X_FO; - case 'o': - if (last) { - return -1; - } - goto X_FO; - default: - return -1; - } - -X_FO: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto X_FOR; - case 'r': - if (last) { - return -1; - } - goto X_FOR; - default: - return -1; - } - -X_FOR: - NEXT_CHAR(); - switch (ch) { - case 'W': - if (last) { - return -1; - } - goto X_FORW; - case 'w': - if (last) { - return -1; - } - goto X_FORW; - default: - return -1; - } - -X_FORW: - NEXT_CHAR(); - switch (ch) { - case 'A': - if (last) { - return -1; - } - goto X_FORWA; - case 'a': - if (last) { - return -1; - } - goto X_FORWA; - default: - return -1; - } - -X_FORWA: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto X_FORWAR; - case 'r': - if (last) { - return -1; - } - goto X_FORWAR; - default: - return -1; - } - -X_FORWAR: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto X_FORWARD; - case 'd': - if (last) { - return -1; - } - goto X_FORWARD; - default: - return -1; - } - -X_FORWARD: - NEXT_CHAR(); - switch (ch) { - case 'E': - if (last) { - return -1; - } - goto X_FORWARDE; - case 'e': - if (last) { - return -1; - } - goto X_FORWARDE; - default: - return -1; - } - -X_FORWARDE: - NEXT_CHAR(); - switch (ch) { - case 'D': - if (last) { - return -1; - } - goto X_FORWARDED; - case 'd': - if (last) { - return -1; - } - goto X_FORWARDED; - default: - return -1; - } - -X_FORWARDED: - NEXT_CHAR(); - switch (ch) { - case '-': - if (last) { - return -1; - } - goto X_FORWARDED_; - default: - return -1; - } - -X_FORWARDED_: - NEXT_CHAR(); - switch (ch) { - case 'F': - if (last) { - return -1; - } - goto X_FORWARDED_F; - case 'f': - if (last) { - return -1; - } - goto X_FORWARDED_F; - case 'H': - if (last) { - return -1; - } - goto X_FORWARDED_H; - case 'h': - if (last) { - return -1; - } - goto X_FORWARDED_H; - case 'P': - if (last) { - return -1; - } - goto X_FORWARDED_P; - case 'p': - if (last) { - return -1; - } - goto X_FORWARDED_P; - default: - return -1; - } - -X_FORWARDED_F: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto X_FORWARDED_FO; - case 'o': - if (last) { - return -1; - } - goto X_FORWARDED_FO; - default: - return -1; - } - -X_FORWARDED_FO: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return 75; - } - goto X_FORWARDED_FOR; - case 'r': - if (last) { - return 75; - } - goto X_FORWARDED_FOR; - default: - return -1; - } - -X_FORWARDED_H: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto X_FORWARDED_HO; - case 'o': - if (last) { - return -1; - } - goto X_FORWARDED_HO; - default: - return -1; - } - -X_FORWARDED_HO: - NEXT_CHAR(); - switch (ch) { - case 'S': - if (last) { - return -1; - } - goto X_FORWARDED_HOS; - case 's': - if (last) { - return -1; - } - goto X_FORWARDED_HOS; - default: - return -1; - } - -X_FORWARDED_HOS: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return 76; - } - goto X_FORWARDED_HOST; - case 't': - if (last) { - return 76; - } - goto X_FORWARDED_HOST; - default: - return -1; - } - -X_FORWARDED_P: - NEXT_CHAR(); - switch (ch) { - case 'R': - if (last) { - return -1; - } - goto X_FORWARDED_PR; - case 'r': - if (last) { - return -1; - } - goto X_FORWARDED_PR; - default: - return -1; - } - -X_FORWARDED_PR: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return -1; - } - goto X_FORWARDED_PRO; - case 'o': - if (last) { - return -1; - } - goto X_FORWARDED_PRO; - default: - return -1; - } - -X_FORWARDED_PRO: - NEXT_CHAR(); - switch (ch) { - case 'T': - if (last) { - return -1; - } - goto X_FORWARDED_PROT; - case 't': - if (last) { - return -1; - } - goto X_FORWARDED_PROT; - default: - return -1; - } - -X_FORWARDED_PROT: - NEXT_CHAR(); - switch (ch) { - case 'O': - if (last) { - return 77; - } - goto X_FORWARDED_PROTO; - case 'o': - if (last) { - return 77; - } - goto X_FORWARDED_PROTO; - default: - return -1; - } - -ACCEPT_CHARSET: -ACCEPT_ENCODING: -ACCEPT_LANGUAGE: -ACCEPT_RANGES: -ACCESS_CONTROL_ALLOW_CREDENTIALS: -ACCESS_CONTROL_ALLOW_HEADERS: -ACCESS_CONTROL_ALLOW_METHODS: -ACCESS_CONTROL_ALLOW_ORIGIN: -ACCESS_CONTROL_EXPOSE_HEADERS: -ACCESS_CONTROL_MAX_AGE: -ACCESS_CONTROL_REQUEST_HEADERS: -ACCESS_CONTROL_REQUEST_METHOD: -AGE: -ALLOW: -AUTHORIZATION: -CACHE_CONTROL: -CONNECTION: -CONTENT_DISPOSITION: -CONTENT_ENCODING: -CONTENT_LANGUAGE: -CONTENT_LENGTH: -CONTENT_LOCATION: -CONTENT_MD5: -CONTENT_RANGE: -CONTENT_TRANSFER_ENCODING: -CONTENT_TYPE: -COOKIE: -DATE: -DESTINATION: -DIGEST: -ETAG: -EXPECT: -EXPIRES: -FORWARDED: -FROM: -HOST: -IF_MATCH: -IF_MODIFIED_SINCE: -IF_NONE_MATCH: -IF_RANGE: -IF_UNMODIFIED_SINCE: -KEEP_ALIVE: -LAST_EVENT_ID: -LAST_MODIFIED: -LINK: -LOCATION: -MAX_FORWARDS: -ORIGIN: -PRAGMA: -PROXY_AUTHENTICATE: -PROXY_AUTHORIZATION: -RANGE: -REFERER: -RETRY_AFTER: -SEC_WEBSOCKET_ACCEPT: -SEC_WEBSOCKET_EXTENSIONS: -SEC_WEBSOCKET_KEY1: -SEC_WEBSOCKET_PROTOCOL: -SEC_WEBSOCKET_VERSION: -SERVER: -SET_COOKIE: -TE: -TRAILER: -TRANSFER_ENCODING: -UPGRADE: -URI: -USER_AGENT: -VARY: -VIA: -WANT_DIGEST: -WARNING: -WEBSOCKET: -WWW_AUTHENTICATE: -X_FORWARDED_FOR: -X_FORWARDED_HOST: -X_FORWARDED_PROTO: -missing: - /* nothing found */ - return -1; -} diff --git a/venv/Lib/site-packages/aiohttp/_find_header.h b/venv/Lib/site-packages/aiohttp/_find_header.h deleted file mode 100644 index 99b7b4f8..00000000 --- a/venv/Lib/site-packages/aiohttp/_find_header.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _FIND_HEADERS_H -#define _FIND_HEADERS_H - -#ifdef __cplusplus -extern "C" { -#endif - -int find_header(const char *str, int size); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/venv/Lib/site-packages/aiohttp/_find_header.pxd b/venv/Lib/site-packages/aiohttp/_find_header.pxd deleted file mode 100644 index 37a6c372..00000000 --- a/venv/Lib/site-packages/aiohttp/_find_header.pxd +++ /dev/null @@ -1,2 +0,0 @@ -cdef extern from "_find_header.h": - int find_header(char *, int) diff --git a/venv/Lib/site-packages/aiohttp/_frozenlist.c b/venv/Lib/site-packages/aiohttp/_frozenlist.c deleted file mode 100644 index 9a57c87f..00000000 --- a/venv/Lib/site-packages/aiohttp/_frozenlist.c +++ /dev/null @@ -1,7355 +0,0 @@ -/* Generated by Cython 0.29.13 */ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#ifndef Py_PYTHON_H - #error Python headers needed to compile C extensions, please install development version of Python. -#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) - #error Cython requires Python 2.6+ or Python 3.3+. -#else -#define CYTHON_ABI "0_29_13" -#define CYTHON_HEX_VERSION 0x001D0DF0 -#define CYTHON_FUTURE_DIVISION 1 -#include -#ifndef offsetof - #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) -#endif -#if !defined(WIN32) && !defined(MS_WINDOWS) - #ifndef __stdcall - #define __stdcall - #endif - #ifndef __cdecl - #define __cdecl - #endif - #ifndef __fastcall - #define __fastcall - #endif -#endif -#ifndef DL_IMPORT - #define DL_IMPORT(t) t -#endif -#ifndef DL_EXPORT - #define DL_EXPORT(t) t -#endif -#define __PYX_COMMA , -#ifndef HAVE_LONG_LONG - #if PY_VERSION_HEX >= 0x02070000 - #define HAVE_LONG_LONG - #endif -#endif -#ifndef PY_LONG_LONG - #define PY_LONG_LONG LONG_LONG -#endif -#ifndef Py_HUGE_VAL - #define Py_HUGE_VAL HUGE_VAL -#endif -#ifdef PYPY_VERSION - #define CYTHON_COMPILING_IN_PYPY 1 - #define CYTHON_COMPILING_IN_PYSTON 0 - #define CYTHON_COMPILING_IN_CPYTHON 0 - #undef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 0 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #if PY_VERSION_HEX < 0x03050000 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #elif !defined(CYTHON_USE_ASYNC_SLOTS) - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #undef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 0 - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #undef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 1 - #undef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 0 - #undef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 0 - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #undef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 0 - #undef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 0 - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 -#elif defined(PYSTON_VERSION) - #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 1 - #define CYTHON_COMPILING_IN_CPYTHON 0 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #undef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 0 - #undef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 0 - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 -#else - #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 0 - #define CYTHON_COMPILING_IN_CPYTHON 1 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) - #define CYTHON_USE_PYTYPE_LOOKUP 1 - #endif - #if PY_MAJOR_VERSION < 3 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #elif !defined(CYTHON_USE_ASYNC_SLOTS) - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #elif !defined(CYTHON_USE_PYLONG_INTERNALS) - #define CYTHON_USE_PYLONG_INTERNALS 1 - #endif - #ifndef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 1 - #endif - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #if PY_VERSION_HEX < 0x030300F0 - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #elif !defined(CYTHON_USE_UNICODE_WRITER) - #define CYTHON_USE_UNICODE_WRITER 1 - #endif - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #ifndef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 1 - #endif - #ifndef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 1 - #endif - #ifndef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) - #endif - #ifndef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) - #endif - #ifndef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) - #endif - #ifndef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) - #endif -#endif -#if !defined(CYTHON_FAST_PYCCALL) -#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) -#endif -#if CYTHON_USE_PYLONG_INTERNALS - #include "longintrepr.h" - #undef SHIFT - #undef BASE - #undef MASK - #ifdef SIZEOF_VOID_P - enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; - #endif -#endif -#ifndef __has_attribute - #define __has_attribute(x) 0 -#endif -#ifndef __has_cpp_attribute - #define __has_cpp_attribute(x) 0 -#endif -#ifndef CYTHON_RESTRICT - #if defined(__GNUC__) - #define CYTHON_RESTRICT __restrict__ - #elif defined(_MSC_VER) && _MSC_VER >= 1400 - #define CYTHON_RESTRICT __restrict - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_RESTRICT restrict - #else - #define CYTHON_RESTRICT - #endif -#endif -#ifndef CYTHON_UNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -#endif -#ifndef CYTHON_MAYBE_UNUSED_VAR -# if defined(__cplusplus) - template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } -# else -# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) -# endif -#endif -#ifndef CYTHON_NCP_UNUSED -# if CYTHON_COMPILING_IN_CPYTHON -# define CYTHON_NCP_UNUSED -# else -# define CYTHON_NCP_UNUSED CYTHON_UNUSED -# endif -#endif -#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) -#ifdef _MSC_VER - #ifndef _MSC_STDINT_H_ - #if _MSC_VER < 1300 - typedef unsigned char uint8_t; - typedef unsigned int uint32_t; - #else - typedef unsigned __int8 uint8_t; - typedef unsigned __int32 uint32_t; - #endif - #endif -#else - #include -#endif -#ifndef CYTHON_FALLTHROUGH - #if defined(__cplusplus) && __cplusplus >= 201103L - #if __has_cpp_attribute(fallthrough) - #define CYTHON_FALLTHROUGH [[fallthrough]] - #elif __has_cpp_attribute(clang::fallthrough) - #define CYTHON_FALLTHROUGH [[clang::fallthrough]] - #elif __has_cpp_attribute(gnu::fallthrough) - #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] - #endif - #endif - #ifndef CYTHON_FALLTHROUGH - #if __has_attribute(fallthrough) - #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) - #else - #define CYTHON_FALLTHROUGH - #endif - #endif - #if defined(__clang__ ) && defined(__apple_build_version__) - #if __apple_build_version__ < 7000000 - #undef CYTHON_FALLTHROUGH - #define CYTHON_FALLTHROUGH - #endif - #endif -#endif - -#ifndef CYTHON_INLINE - #if defined(__clang__) - #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) - #elif defined(__GNUC__) - #define CYTHON_INLINE __inline__ - #elif defined(_MSC_VER) - #define CYTHON_INLINE __inline - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_INLINE inline - #else - #define CYTHON_INLINE - #endif -#endif - -#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) - #define Py_OptimizeFlag 0 -#endif -#define __PYX_BUILD_PY_SSIZE_T "n" -#define CYTHON_FORMAT_SSIZE_T "z" -#if PY_MAJOR_VERSION < 3 - #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) - #define __Pyx_DefaultClassType PyClass_Type -#else - #define __Pyx_BUILTIN_MODULE_NAME "builtins" -#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) -#else - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) -#endif - #define __Pyx_DefaultClassType PyType_Type -#endif -#ifndef Py_TPFLAGS_CHECKTYPES - #define Py_TPFLAGS_CHECKTYPES 0 -#endif -#ifndef Py_TPFLAGS_HAVE_INDEX - #define Py_TPFLAGS_HAVE_INDEX 0 -#endif -#ifndef Py_TPFLAGS_HAVE_NEWBUFFER - #define Py_TPFLAGS_HAVE_NEWBUFFER 0 -#endif -#ifndef Py_TPFLAGS_HAVE_FINALIZE - #define Py_TPFLAGS_HAVE_FINALIZE 0 -#endif -#ifndef METH_STACKLESS - #define METH_STACKLESS 0 -#endif -#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) - #ifndef METH_FASTCALL - #define METH_FASTCALL 0x80 - #endif - typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); - typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, - Py_ssize_t nargs, PyObject *kwnames); -#else - #define __Pyx_PyCFunctionFast _PyCFunctionFast - #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords -#endif -#if CYTHON_FAST_PYCCALL -#define __Pyx_PyFastCFunction_Check(func)\ - ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) -#else -#define __Pyx_PyFastCFunction_Check(func) 0 -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) - #define PyObject_Malloc(s) PyMem_Malloc(s) - #define PyObject_Free(p) PyMem_Free(p) - #define PyObject_Realloc(p) PyMem_Realloc(p) -#endif -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 - #define PyMem_RawMalloc(n) PyMem_Malloc(n) - #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) - #define PyMem_RawFree(p) PyMem_Free(p) -#endif -#if CYTHON_COMPILING_IN_PYSTON - #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) - #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) -#else - #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) - #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) -#endif -#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 - #define __Pyx_PyThreadState_Current PyThreadState_GET() -#elif PY_VERSION_HEX >= 0x03060000 - #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() -#elif PY_VERSION_HEX >= 0x03000000 - #define __Pyx_PyThreadState_Current PyThreadState_GET() -#else - #define __Pyx_PyThreadState_Current _PyThreadState_Current -#endif -#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) -#include "pythread.h" -#define Py_tss_NEEDS_INIT 0 -typedef int Py_tss_t; -static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { - *key = PyThread_create_key(); - return 0; -} -static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { - Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); - *key = Py_tss_NEEDS_INIT; - return key; -} -static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { - PyObject_Free(key); -} -static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { - return *key != Py_tss_NEEDS_INIT; -} -static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { - PyThread_delete_key(*key); - *key = Py_tss_NEEDS_INIT; -} -static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { - return PyThread_set_key_value(*key, value); -} -static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { - return PyThread_get_key_value(*key); -} -#endif -#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) -#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) -#else -#define __Pyx_PyDict_NewPresized(n) PyDict_New() -#endif -#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION - #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) -#else - #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) -#endif -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS -#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) -#else -#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) -#endif -#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) - #define CYTHON_PEP393_ENABLED 1 - #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ - 0 : _PyUnicode_Ready((PyObject *)(op))) - #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) - #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) - #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) - #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) - #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) - #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) - #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) -#else - #define CYTHON_PEP393_ENABLED 0 - #define PyUnicode_1BYTE_KIND 1 - #define PyUnicode_2BYTE_KIND 2 - #define PyUnicode_4BYTE_KIND 4 - #define __Pyx_PyUnicode_READY(op) (0) - #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) - #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) - #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) - #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) - #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) - #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) - #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) -#endif -#if CYTHON_COMPILING_IN_PYPY - #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) - #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) -#else - #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) - #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ - PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) - #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) - #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) - #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) -#endif -#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) -#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) -#else - #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) -#endif -#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) - #define PyObject_ASCII(o) PyObject_Repr(o) -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyBaseString_Type PyUnicode_Type - #define PyStringObject PyUnicodeObject - #define PyString_Type PyUnicode_Type - #define PyString_Check PyUnicode_Check - #define PyString_CheckExact PyUnicode_CheckExact - #define PyObject_Unicode PyObject_Str -#endif -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) - #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) -#else - #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) - #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) -#endif -#ifndef PySet_CheckExact - #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) -#endif -#if CYTHON_ASSUME_SAFE_MACROS - #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) -#else - #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyIntObject PyLongObject - #define PyInt_Type PyLong_Type - #define PyInt_Check(op) PyLong_Check(op) - #define PyInt_CheckExact(op) PyLong_CheckExact(op) - #define PyInt_FromString PyLong_FromString - #define PyInt_FromUnicode PyLong_FromUnicode - #define PyInt_FromLong PyLong_FromLong - #define PyInt_FromSize_t PyLong_FromSize_t - #define PyInt_FromSsize_t PyLong_FromSsize_t - #define PyInt_AsLong PyLong_AsLong - #define PyInt_AS_LONG PyLong_AS_LONG - #define PyInt_AsSsize_t PyLong_AsSsize_t - #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask - #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask - #define PyNumber_Int PyNumber_Long -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyBoolObject PyLongObject -#endif -#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY - #ifndef PyUnicode_InternFromString - #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) - #endif -#endif -#if PY_VERSION_HEX < 0x030200A4 - typedef long Py_hash_t; - #define __Pyx_PyInt_FromHash_t PyInt_FromLong - #define __Pyx_PyInt_AsHash_t PyInt_AsLong -#else - #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t - #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t -#endif -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) -#else - #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) -#endif -#if CYTHON_USE_ASYNC_SLOTS - #if PY_VERSION_HEX >= 0x030500B1 - #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods - #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) - #else - #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) - #endif -#else - #define __Pyx_PyType_AsAsync(obj) NULL -#endif -#ifndef __Pyx_PyAsyncMethodsStruct - typedef struct { - unaryfunc am_await; - unaryfunc am_aiter; - unaryfunc am_anext; - } __Pyx_PyAsyncMethodsStruct; -#endif - -#if defined(WIN32) || defined(MS_WINDOWS) - #define _USE_MATH_DEFINES -#endif -#include -#ifdef NAN -#define __PYX_NAN() ((float) NAN) -#else -static CYTHON_INLINE float __PYX_NAN() { - float value; - memset(&value, 0xFF, sizeof(value)); - return value; -} -#endif -#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) -#define __Pyx_truncl trunc -#else -#define __Pyx_truncl truncl -#endif - - -#define __PYX_ERR(f_index, lineno, Ln_error) \ -{ \ - __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \ -} - -#ifndef __PYX_EXTERN_C - #ifdef __cplusplus - #define __PYX_EXTERN_C extern "C" - #else - #define __PYX_EXTERN_C extern - #endif -#endif - -#define __PYX_HAVE__aiohttp___frozenlist -#define __PYX_HAVE_API__aiohttp___frozenlist -/* Early includes */ -#ifdef _OPENMP -#include -#endif /* _OPENMP */ - -#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) -#define CYTHON_WITHOUT_ASSERTIONS -#endif - -typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; - const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; - -#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 -#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 -#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) -#define __PYX_DEFAULT_STRING_ENCODING "" -#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString -#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize -#define __Pyx_uchar_cast(c) ((unsigned char)c) -#define __Pyx_long_cast(x) ((long)x) -#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ - (sizeof(type) < sizeof(Py_ssize_t)) ||\ - (sizeof(type) > sizeof(Py_ssize_t) &&\ - likely(v < (type)PY_SSIZE_T_MAX ||\ - v == (type)PY_SSIZE_T_MAX) &&\ - (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ - v == (type)PY_SSIZE_T_MIN))) ||\ - (sizeof(type) == sizeof(Py_ssize_t) &&\ - (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ - v == (type)PY_SSIZE_T_MAX))) ) -static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { - return (size_t) i < (size_t) limit; -} -#if defined (__cplusplus) && __cplusplus >= 201103L - #include - #define __Pyx_sst_abs(value) std::abs(value) -#elif SIZEOF_INT >= SIZEOF_SIZE_T - #define __Pyx_sst_abs(value) abs(value) -#elif SIZEOF_LONG >= SIZEOF_SIZE_T - #define __Pyx_sst_abs(value) labs(value) -#elif defined (_MSC_VER) - #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) -#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define __Pyx_sst_abs(value) llabs(value) -#elif defined (__GNUC__) - #define __Pyx_sst_abs(value) __builtin_llabs(value) -#else - #define __Pyx_sst_abs(value) ((value<0) ? -value : value) -#endif -static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); -static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); -#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) -#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) -#define __Pyx_PyBytes_FromString PyBytes_FromString -#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize -static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); -#if PY_MAJOR_VERSION < 3 - #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString - #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize -#else - #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString - #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize -#endif -#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) -#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) -#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) -#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) -#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) -static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { - const Py_UNICODE *u_end = u; - while (*u_end++) ; - return (size_t)(u_end - u - 1); -} -#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) -#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode -#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode -#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) -#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) -static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); -static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); -static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); -static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); -#define __Pyx_PySequence_Tuple(obj)\ - (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) -static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); -#if CYTHON_ASSUME_SAFE_MACROS -#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) -#else -#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) -#endif -#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) -#if PY_MAJOR_VERSION >= 3 -#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) -#else -#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) -#endif -#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) -#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII -static int __Pyx_sys_getdefaultencoding_not_ascii; -static int __Pyx_init_sys_getdefaultencoding_params(void) { - PyObject* sys; - PyObject* default_encoding = NULL; - PyObject* ascii_chars_u = NULL; - PyObject* ascii_chars_b = NULL; - const char* default_encoding_c; - sys = PyImport_ImportModule("sys"); - if (!sys) goto bad; - default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); - Py_DECREF(sys); - if (!default_encoding) goto bad; - default_encoding_c = PyBytes_AsString(default_encoding); - if (!default_encoding_c) goto bad; - if (strcmp(default_encoding_c, "ascii") == 0) { - __Pyx_sys_getdefaultencoding_not_ascii = 0; - } else { - char ascii_chars[128]; - int c; - for (c = 0; c < 128; c++) { - ascii_chars[c] = c; - } - __Pyx_sys_getdefaultencoding_not_ascii = 1; - ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); - if (!ascii_chars_u) goto bad; - ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); - if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { - PyErr_Format( - PyExc_ValueError, - "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", - default_encoding_c); - goto bad; - } - Py_DECREF(ascii_chars_u); - Py_DECREF(ascii_chars_b); - } - Py_DECREF(default_encoding); - return 0; -bad: - Py_XDECREF(default_encoding); - Py_XDECREF(ascii_chars_u); - Py_XDECREF(ascii_chars_b); - return -1; -} -#endif -#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 -#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) -#else -#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) -#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT -static char* __PYX_DEFAULT_STRING_ENCODING; -static int __Pyx_init_sys_getdefaultencoding_params(void) { - PyObject* sys; - PyObject* default_encoding = NULL; - char* default_encoding_c; - sys = PyImport_ImportModule("sys"); - if (!sys) goto bad; - default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); - Py_DECREF(sys); - if (!default_encoding) goto bad; - default_encoding_c = PyBytes_AsString(default_encoding); - if (!default_encoding_c) goto bad; - __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); - if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; - strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); - Py_DECREF(default_encoding); - return 0; -bad: - Py_XDECREF(default_encoding); - return -1; -} -#endif -#endif - - -/* Test for GCC > 2.95 */ -#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) - #define likely(x) __builtin_expect(!!(x), 1) - #define unlikely(x) __builtin_expect(!!(x), 0) -#else /* !__GNUC__ or GCC < 2.95 */ - #define likely(x) (x) - #define unlikely(x) (x) -#endif /* __GNUC__ */ -static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } - -static PyObject *__pyx_m = NULL; -static PyObject *__pyx_d; -static PyObject *__pyx_b; -static PyObject *__pyx_cython_runtime = NULL; -static PyObject *__pyx_empty_tuple; -static PyObject *__pyx_empty_bytes; -static PyObject *__pyx_empty_unicode; -static int __pyx_lineno; -static int __pyx_clineno = 0; -static const char * __pyx_cfilenm= __FILE__; -static const char *__pyx_filename; - - -static const char *__pyx_f[] = { - "aiohttp\\_frozenlist.pyx", - "stringsource", -}; - -/*--- Type declarations ---*/ -struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList; - -/* "aiohttp/_frozenlist.pyx":4 - * - * - * cdef class FrozenList: # <<<<<<<<<<<<<< - * - * cdef readonly bint frozen - */ -struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList { - PyObject_HEAD - struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *__pyx_vtab; - int frozen; - PyObject *_items; -}; - - - -struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList { - PyObject *(*_check_frozen)(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *); - PyObject *(*_fast_len)(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *); -}; -static struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *__pyx_vtabptr_7aiohttp_11_frozenlist_FrozenList; -static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *); - -/* --- Runtime support code (head) --- */ -/* Refnanny.proto */ -#ifndef CYTHON_REFNANNY - #define CYTHON_REFNANNY 0 -#endif -#if CYTHON_REFNANNY - typedef struct { - void (*INCREF)(void*, PyObject*, int); - void (*DECREF)(void*, PyObject*, int); - void (*GOTREF)(void*, PyObject*, int); - void (*GIVEREF)(void*, PyObject*, int); - void* (*SetupContext)(const char*, int, const char*); - void (*FinishContext)(void**); - } __Pyx_RefNannyAPIStruct; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); - #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; -#ifdef WITH_THREAD - #define __Pyx_RefNannySetupContext(name, acquire_gil)\ - if (acquire_gil) {\ - PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ - PyGILState_Release(__pyx_gilstate_save);\ - } else {\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ - } -#else - #define __Pyx_RefNannySetupContext(name, acquire_gil)\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) -#endif - #define __Pyx_RefNannyFinishContext()\ - __Pyx_RefNanny->FinishContext(&__pyx_refnanny) - #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) - #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) - #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) - #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) -#else - #define __Pyx_RefNannyDeclarations - #define __Pyx_RefNannySetupContext(name, acquire_gil) - #define __Pyx_RefNannyFinishContext() - #define __Pyx_INCREF(r) Py_INCREF(r) - #define __Pyx_DECREF(r) Py_DECREF(r) - #define __Pyx_GOTREF(r) - #define __Pyx_GIVEREF(r) - #define __Pyx_XINCREF(r) Py_XINCREF(r) - #define __Pyx_XDECREF(r) Py_XDECREF(r) - #define __Pyx_XGOTREF(r) - #define __Pyx_XGIVEREF(r) -#endif -#define __Pyx_XDECREF_SET(r, v) do {\ - PyObject *tmp = (PyObject *) r;\ - r = v; __Pyx_XDECREF(tmp);\ - } while (0) -#define __Pyx_DECREF_SET(r, v) do {\ - PyObject *tmp = (PyObject *) r;\ - r = v; __Pyx_DECREF(tmp);\ - } while (0) -#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) -#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) - -/* PyObjectGetAttrStr.proto */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); -#else -#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) -#endif - -/* GetBuiltinName.proto */ -static PyObject *__Pyx_GetBuiltinName(PyObject *name); - -/* RaiseDoubleKeywords.proto */ -static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); - -/* ParseKeywords.proto */ -static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ - PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ - const char* function_name); - -/* RaiseArgTupleInvalid.proto */ -static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, - Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); - -/* PyObjectCall.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); -#else -#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) -#endif - -/* PyThreadStateGet.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; -#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; -#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type -#else -#define __Pyx_PyThreadState_declare -#define __Pyx_PyThreadState_assign -#define __Pyx_PyErr_Occurred() PyErr_Occurred() -#endif - -/* PyErrFetchRestore.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) -#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) -#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) -#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) -#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) -static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); -static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) -#else -#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) -#endif -#else -#define __Pyx_PyErr_Clear() PyErr_Clear() -#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) -#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) -#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) -#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) -#endif - -/* RaiseException.proto */ -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); - -/* GetItemInt.proto */ -#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\ - (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ - __Pyx_GetItemInt_Generic(o, to_py_func(i)))) -#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ - (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ - (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, - int is_list, int wraparound, int boundscheck); - -/* ObjectGetItem.proto */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key); -#else -#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) -#endif - -/* PyFunctionFastCall.proto */ -#if CYTHON_FAST_PYCALL -#define __Pyx_PyFunction_FastCall(func, args, nargs)\ - __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); -#else -#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) -#endif -#define __Pyx_BUILD_ASSERT_EXPR(cond)\ - (sizeof(char [1 - 2*!(cond)]) - 1) -#ifndef Py_MEMBER_SIZE -#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) -#endif - static size_t __pyx_pyframe_localsplus_offset = 0; - #include "frameobject.h" - #define __Pxy_PyFrame_Initialize_Offsets()\ - ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ - (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) - #define __Pyx_PyFrame_GetLocalsplus(frame)\ - (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) -#endif - -/* PyObjectCallMethO.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); -#endif - -/* PyObjectCallNoArg.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); -#else -#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) -#endif - -/* PyCFunctionFastCall.proto */ -#if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); -#else -#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) -#endif - -/* PyObjectCallOneArg.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); - -/* PyIntCompare.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_EqObjC(PyObject *op1, PyObject *op2, long intval, long inplace); - -/* PySequenceContains.proto */ -static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) { - int result = PySequence_Contains(seq, item); - return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); -} - -/* PyObjectCall2Args.proto */ -static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); - -/* PyObjectGetMethod.proto */ -static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); - -/* PyObjectCallMethod1.proto */ -static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg); - -/* pop_index.proto */ -static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix); -static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix); -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix); -#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\ - (likely(PyList_CheckExact(L) && __Pyx_fits_Py_ssize_t(ix, type, is_signed))) ?\ - __Pyx__PyList_PopIndex(L, py_ix, ix) : (\ - (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\ - __Pyx__PyObject_PopIndex(L, py_ix))) -#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\ - __Pyx_fits_Py_ssize_t(ix, type, is_signed) ?\ - __Pyx__PyList_PopIndex(L, py_ix, ix) : (\ - (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\ - __Pyx__PyObject_PopIndex(L, py_ix))) -#else -#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func)\ - __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) -#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\ - (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\ - __Pyx__PyObject_PopIndex(L, py_ix)) -#endif - -/* ListAppend.proto */ -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { - PyListObject* L = (PyListObject*) list; - Py_ssize_t len = Py_SIZE(list); - if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) { - Py_INCREF(x); - PyList_SET_ITEM(list, len, x); - Py_SIZE(list) = len+1; - return 0; - } - return PyList_Append(list, x); -} -#else -#define __Pyx_PyList_Append(L,x) PyList_Append(L,x) -#endif - -/* PyErrExceptionMatches.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) -static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); -#else -#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) -#endif - -/* GetAttr.proto */ -static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *, PyObject *); - -/* GetAttr3.proto */ -static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); - -/* PyDictVersioning.proto */ -#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) -#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) -#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ - (version_var) = __PYX_GET_DICT_VERSION(dict);\ - (cache_var) = (value); -#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ - static PY_UINT64_T __pyx_dict_version = 0;\ - static PyObject *__pyx_dict_cached_value = NULL;\ - if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ - (VAR) = __pyx_dict_cached_value;\ - } else {\ - (VAR) = __pyx_dict_cached_value = (LOOKUP);\ - __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ - }\ -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); -#else -#define __PYX_GET_DICT_VERSION(dict) (0) -#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) -#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); -#endif - -/* GetModuleGlobalName.proto */ -#if CYTHON_USE_DICT_VERSIONS -#define __Pyx_GetModuleGlobalName(var, name) {\ - static PY_UINT64_T __pyx_dict_version = 0;\ - static PyObject *__pyx_dict_cached_value = NULL;\ - (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ - (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ - __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ -} -#define __Pyx_GetModuleGlobalNameUncached(var, name) {\ - PY_UINT64_T __pyx_dict_version;\ - PyObject *__pyx_dict_cached_value;\ - (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ -} -static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); -#else -#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) -#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) -static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); -#endif - -/* Import.proto */ -static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); - -/* ImportFrom.proto */ -static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); - -/* HasAttr.proto */ -static CYTHON_INLINE int __Pyx_HasAttr(PyObject *, PyObject *); - -/* PyObject_GenericGetAttrNoDict.proto */ -#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name); -#else -#define __Pyx_PyObject_GenericGetAttrNoDict PyObject_GenericGetAttr -#endif - -/* PyObject_GenericGetAttr.proto */ -#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name); -#else -#define __Pyx_PyObject_GenericGetAttr PyObject_GenericGetAttr -#endif - -/* SetVTable.proto */ -static int __Pyx_SetVtable(PyObject *dict, void *vtable); - -/* SetupReduce.proto */ -static int __Pyx_setup_reduce(PyObject* type_obj); - -/* CLineInTraceback.proto */ -#ifdef CYTHON_CLINE_IN_TRACEBACK -#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) -#else -static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); -#endif - -/* CodeObjectCache.proto */ -typedef struct { - PyCodeObject* code_object; - int code_line; -} __Pyx_CodeObjectCacheEntry; -struct __Pyx_CodeObjectCache { - int count; - int max_count; - __Pyx_CodeObjectCacheEntry* entries; -}; -static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; -static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); -static PyCodeObject *__pyx_find_code_object(int code_line); -static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); - -/* AddTraceback.proto */ -static void __Pyx_AddTraceback(const char *funcname, int c_line, - int py_line, const char *filename); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); - -/* CIntFromPy.proto */ -static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); - -/* CIntFromPy.proto */ -static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); - -/* FastTypeChecks.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) -static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); -static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); -static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); -#else -#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) -#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) -#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) -#endif -#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) - -/* CheckBinaryVersion.proto */ -static int __Pyx_check_binary_version(void); - -/* InitStrings.proto */ -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); - -static PyObject *__pyx_f_7aiohttp_11_frozenlist_10FrozenList__check_frozen(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto*/ -static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto*/ - -/* Module declarations from 'aiohttp._frozenlist' */ -static PyTypeObject *__pyx_ptype_7aiohttp_11_frozenlist_FrozenList = 0; -static PyObject *__pyx_f_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList__set_state(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *, PyObject *); /*proto*/ -#define __Pyx_MODULE_NAME "aiohttp._frozenlist" -extern int __pyx_module_is_main_aiohttp___frozenlist; -int __pyx_module_is_main_aiohttp___frozenlist = 0; - -/* Implementation of 'aiohttp._frozenlist' */ -static PyObject *__pyx_builtin_RuntimeError; -static const char __pyx_k_new[] = "__new__"; -static const char __pyx_k_pop[] = "pop"; -static const char __pyx_k_pos[] = "pos"; -static const char __pyx_k_dict[] = "__dict__"; -static const char __pyx_k_item[] = "item"; -static const char __pyx_k_iter[] = "__iter__"; -static const char __pyx_k_main[] = "__main__"; -static const char __pyx_k_name[] = "__name__"; -static const char __pyx_k_test[] = "__test__"; -static const char __pyx_k_clear[] = "clear"; -static const char __pyx_k_count[] = "count"; -static const char __pyx_k_index[] = "index"; -static const char __pyx_k_items[] = "items"; -static const char __pyx_k_format[] = "format"; -static const char __pyx_k_import[] = "__import__"; -static const char __pyx_k_pickle[] = "pickle"; -static const char __pyx_k_reduce[] = "__reduce__"; -static const char __pyx_k_remove[] = "remove"; -static const char __pyx_k_update[] = "update"; -static const char __pyx_k_getstate[] = "__getstate__"; -static const char __pyx_k_pyx_type[] = "__pyx_type"; -static const char __pyx_k_register[] = "register"; -static const char __pyx_k_reversed[] = "__reversed__"; -static const char __pyx_k_setstate[] = "__setstate__"; -static const char __pyx_k_pyx_state[] = "__pyx_state"; -static const char __pyx_k_reduce_ex[] = "__reduce_ex__"; -static const char __pyx_k_FrozenList[] = "FrozenList"; -static const char __pyx_k_pyx_result[] = "__pyx_result"; -static const char __pyx_k_pyx_vtable[] = "__pyx_vtable__"; -static const char __pyx_k_PickleError[] = "PickleError"; -static const char __pyx_k_RuntimeError[] = "RuntimeError"; -static const char __pyx_k_pyx_checksum[] = "__pyx_checksum"; -static const char __pyx_k_stringsource[] = "stringsource"; -static const char __pyx_k_reduce_cython[] = "__reduce_cython__"; -static const char __pyx_k_MutableSequence[] = "MutableSequence"; -static const char __pyx_k_collections_abc[] = "collections.abc"; -static const char __pyx_k_pyx_PickleError[] = "__pyx_PickleError"; -static const char __pyx_k_setstate_cython[] = "__setstate_cython__"; -static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; -static const char __pyx_k_FrozenList_frozen_r[] = ""; -static const char __pyx_k_aiohttp__frozenlist[] = "aiohttp._frozenlist"; -static const char __pyx_k_pyx_unpickle_FrozenList[] = "__pyx_unpickle_FrozenList"; -static const char __pyx_k_Cannot_modify_frozen_list[] = "Cannot modify frozen list."; -static const char __pyx_k_Incompatible_checksums_s_vs_0x94[] = "Incompatible checksums (%s vs 0x949a143 = (_items, frozen))"; -static PyObject *__pyx_kp_u_Cannot_modify_frozen_list; -static PyObject *__pyx_n_s_FrozenList; -static PyObject *__pyx_kp_u_FrozenList_frozen_r; -static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0x94; -static PyObject *__pyx_n_s_MutableSequence; -static PyObject *__pyx_n_s_PickleError; -static PyObject *__pyx_n_s_RuntimeError; -static PyObject *__pyx_n_s_aiohttp__frozenlist; -static PyObject *__pyx_n_s_clear; -static PyObject *__pyx_n_s_cline_in_traceback; -static PyObject *__pyx_n_s_collections_abc; -static PyObject *__pyx_n_s_count; -static PyObject *__pyx_n_s_dict; -static PyObject *__pyx_n_s_format; -static PyObject *__pyx_n_s_getstate; -static PyObject *__pyx_n_s_import; -static PyObject *__pyx_n_s_index; -static PyObject *__pyx_n_s_item; -static PyObject *__pyx_n_s_items; -static PyObject *__pyx_n_s_iter; -static PyObject *__pyx_n_s_main; -static PyObject *__pyx_n_s_name; -static PyObject *__pyx_n_s_new; -static PyObject *__pyx_n_s_pickle; -static PyObject *__pyx_n_s_pop; -static PyObject *__pyx_n_s_pos; -static PyObject *__pyx_n_s_pyx_PickleError; -static PyObject *__pyx_n_s_pyx_checksum; -static PyObject *__pyx_n_s_pyx_result; -static PyObject *__pyx_n_s_pyx_state; -static PyObject *__pyx_n_s_pyx_type; -static PyObject *__pyx_n_s_pyx_unpickle_FrozenList; -static PyObject *__pyx_n_s_pyx_vtable; -static PyObject *__pyx_n_s_reduce; -static PyObject *__pyx_n_s_reduce_cython; -static PyObject *__pyx_n_s_reduce_ex; -static PyObject *__pyx_n_s_register; -static PyObject *__pyx_n_s_remove; -static PyObject *__pyx_n_s_reversed; -static PyObject *__pyx_n_s_setstate; -static PyObject *__pyx_n_s_setstate_cython; -static PyObject *__pyx_kp_s_stringsource; -static PyObject *__pyx_n_s_test; -static PyObject *__pyx_n_s_update; -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList___init__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_2freeze(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_4__getitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index); /* proto */ -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6__setitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value); /* proto */ -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_8__delitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index); /* proto */ -static Py_ssize_t __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_10__len__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_12__iter__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_14__reversed__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_16__richcmp__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_other, PyObject *__pyx_v_op); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_18insert(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_pos, PyObject *__pyx_v_item); /* proto */ -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_20__contains__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_22__iadd__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_24index(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_26remove(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_28clear(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_30extend(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_32reverse(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_34pop(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_36append(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_38count(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_40__repr__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6frozen___get__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_42__reduce_cython__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_44__setstate_cython__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ -static PyObject *__pyx_pf_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ -static PyObject *__pyx_tp_new_7aiohttp_11_frozenlist_FrozenList(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ -static PyObject *__pyx_int_0; -static PyObject *__pyx_int_1; -static PyObject *__pyx_int_2; -static PyObject *__pyx_int_3; -static PyObject *__pyx_int_4; -static PyObject *__pyx_int_5; -static PyObject *__pyx_int_155820355; -static PyObject *__pyx_int_neg_1; -static PyObject *__pyx_tuple_; -static PyObject *__pyx_tuple__2; -static PyObject *__pyx_codeobj__3; -/* Late includes */ - -/* "aiohttp/_frozenlist.pyx":9 - * cdef list _items - * - * def __init__(self, items=None): # <<<<<<<<<<<<<< - * self.frozen = False - * if items is not None: - */ - -/* Python wrapper */ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_items = 0; - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_items,0}; - PyObject* values[1] = {0}; - values[0] = ((PyObject *)Py_None); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (kw_args > 0) { - PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_items); - if (value) { values[0] = value; kw_args--; } - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 9, __pyx_L3_error) - } - } else { - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - } - __pyx_v_items = values[0]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 9, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return -1; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList___init__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), __pyx_v_items); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList___init__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items) { - int __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - __Pyx_RefNannySetupContext("__init__", 0); - __Pyx_INCREF(__pyx_v_items); - - /* "aiohttp/_frozenlist.pyx":10 - * - * def __init__(self, items=None): - * self.frozen = False # <<<<<<<<<<<<<< - * if items is not None: - * items = list(items) - */ - __pyx_v_self->frozen = 0; - - /* "aiohttp/_frozenlist.pyx":11 - * def __init__(self, items=None): - * self.frozen = False - * if items is not None: # <<<<<<<<<<<<<< - * items = list(items) - * else: - */ - __pyx_t_1 = (__pyx_v_items != Py_None); - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":12 - * self.frozen = False - * if items is not None: - * items = list(items) # <<<<<<<<<<<<<< - * else: - * items = [] - */ - __pyx_t_3 = PySequence_List(__pyx_v_items); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 12, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_items, __pyx_t_3); - __pyx_t_3 = 0; - - /* "aiohttp/_frozenlist.pyx":11 - * def __init__(self, items=None): - * self.frozen = False - * if items is not None: # <<<<<<<<<<<<<< - * items = list(items) - * else: - */ - goto __pyx_L3; - } - - /* "aiohttp/_frozenlist.pyx":14 - * items = list(items) - * else: - * items = [] # <<<<<<<<<<<<<< - * self._items = items - * - */ - /*else*/ { - __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF_SET(__pyx_v_items, __pyx_t_3); - __pyx_t_3 = 0; - } - __pyx_L3:; - - /* "aiohttp/_frozenlist.pyx":15 - * else: - * items = [] - * self._items = items # <<<<<<<<<<<<<< - * - * cdef object _check_frozen(self): - */ - if (!(likely(PyList_CheckExact(__pyx_v_items))||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "list", Py_TYPE(__pyx_v_items)->tp_name), 0))) __PYX_ERR(0, 15, __pyx_L1_error) - __pyx_t_3 = __pyx_v_items; - __Pyx_INCREF(__pyx_t_3); - __Pyx_GIVEREF(__pyx_t_3); - __Pyx_GOTREF(__pyx_v_self->_items); - __Pyx_DECREF(__pyx_v_self->_items); - __pyx_v_self->_items = ((PyObject*)__pyx_t_3); - __pyx_t_3 = 0; - - /* "aiohttp/_frozenlist.pyx":9 - * cdef list _items - * - * def __init__(self, items=None): # <<<<<<<<<<<<<< - * self.frozen = False - * if items is not None: - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_items); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":17 - * self._items = items - * - * cdef object _check_frozen(self): # <<<<<<<<<<<<<< - * if self.frozen: - * raise RuntimeError("Cannot modify frozen list.") - */ - -static PyObject *__pyx_f_7aiohttp_11_frozenlist_10FrozenList__check_frozen(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - __Pyx_RefNannySetupContext("_check_frozen", 0); - - /* "aiohttp/_frozenlist.pyx":18 - * - * cdef object _check_frozen(self): - * if self.frozen: # <<<<<<<<<<<<<< - * raise RuntimeError("Cannot modify frozen list.") - * - */ - __pyx_t_1 = (__pyx_v_self->frozen != 0); - if (unlikely(__pyx_t_1)) { - - /* "aiohttp/_frozenlist.pyx":19 - * cdef object _check_frozen(self): - * if self.frozen: - * raise RuntimeError("Cannot modify frozen list.") # <<<<<<<<<<<<<< - * - * cdef inline object _fast_len(self): - */ - __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_RuntimeError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 19, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_Raise(__pyx_t_2, 0, 0, 0); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __PYX_ERR(0, 19, __pyx_L1_error) - - /* "aiohttp/_frozenlist.pyx":18 - * - * cdef object _check_frozen(self): - * if self.frozen: # <<<<<<<<<<<<<< - * raise RuntimeError("Cannot modify frozen list.") - * - */ - } - - /* "aiohttp/_frozenlist.pyx":17 - * self._items = items - * - * cdef object _check_frozen(self): # <<<<<<<<<<<<<< - * if self.frozen: - * raise RuntimeError("Cannot modify frozen list.") - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList._check_frozen", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":21 - * raise RuntimeError("Cannot modify frozen list.") - * - * cdef inline object _fast_len(self): # <<<<<<<<<<<<<< - * return len(self._items) - * - */ - -static CYTHON_INLINE PyObject *__pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - Py_ssize_t __pyx_t_2; - __Pyx_RefNannySetupContext("_fast_len", 0); - - /* "aiohttp/_frozenlist.pyx":22 - * - * cdef inline object _fast_len(self): - * return len(self._items) # <<<<<<<<<<<<<< - * - * def freeze(self): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __pyx_v_self->_items; - __Pyx_INCREF(__pyx_t_1); - if (unlikely(__pyx_t_1 == Py_None)) { - PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(0, 22, __pyx_L1_error) - } - __pyx_t_2 = PyList_GET_SIZE(__pyx_t_1); if (unlikely(__pyx_t_2 == ((Py_ssize_t)-1))) __PYX_ERR(0, 22, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 22, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":21 - * raise RuntimeError("Cannot modify frozen list.") - * - * cdef inline object _fast_len(self): # <<<<<<<<<<<<<< - * return len(self._items) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList._fast_len", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":24 - * return len(self._items) - * - * def freeze(self): # <<<<<<<<<<<<<< - * self.frozen = True - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_3freeze(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_3freeze(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("freeze (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_2freeze(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_2freeze(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("freeze", 0); - - /* "aiohttp/_frozenlist.pyx":25 - * - * def freeze(self): - * self.frozen = True # <<<<<<<<<<<<<< - * - * def __getitem__(self, index): - */ - __pyx_v_self->frozen = 1; - - /* "aiohttp/_frozenlist.pyx":24 - * return len(self._items) - * - * def freeze(self): # <<<<<<<<<<<<<< - * self.frozen = True - * - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":27 - * self.frozen = True - * - * def __getitem__(self, index): # <<<<<<<<<<<<<< - * return self._items[index] - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_5__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_5__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_4__getitem__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_index)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_4__getitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - __Pyx_RefNannySetupContext("__getitem__", 0); - - /* "aiohttp/_frozenlist.pyx":28 - * - * def __getitem__(self, index): - * return self._items[index] # <<<<<<<<<<<<<< - * - * def __setitem__(self, index, value): - */ - __Pyx_XDECREF(__pyx_r); - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 28, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_v_self->_items, __pyx_v_index); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 28, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":27 - * self.frozen = True - * - * def __getitem__(self, index): # <<<<<<<<<<<<<< - * return self._items[index] - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":30 - * return self._items[index] - * - * def __setitem__(self, index, value): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items[index] = value - */ - -/* Python wrapper */ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_7__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value); /*proto*/ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_7__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__setitem__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6__setitem__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_index), ((PyObject *)__pyx_v_value)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6__setitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value) { - int __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - __Pyx_RefNannySetupContext("__setitem__", 0); - - /* "aiohttp/_frozenlist.pyx":31 - * - * def __setitem__(self, index, value): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items[index] = value - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 31, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":32 - * def __setitem__(self, index, value): - * self._check_frozen() - * self._items[index] = value # <<<<<<<<<<<<<< - * - * def __delitem__(self, index): - */ - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 32, __pyx_L1_error) - } - if (unlikely(PyObject_SetItem(__pyx_v_self->_items, __pyx_v_index, __pyx_v_value) < 0)) __PYX_ERR(0, 32, __pyx_L1_error) - - /* "aiohttp/_frozenlist.pyx":30 - * return self._items[index] - * - * def __setitem__(self, index, value): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items[index] = value - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__setitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":34 - * self._items[index] = value - * - * def __delitem__(self, index): # <<<<<<<<<<<<<< - * self._check_frozen() - * del self._items[index] - */ - -/* Python wrapper */ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_9__delitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index); /*proto*/ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_9__delitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__delitem__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_8__delitem__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_index)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_8__delitem__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index) { - int __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - __Pyx_RefNannySetupContext("__delitem__", 0); - - /* "aiohttp/_frozenlist.pyx":35 - * - * def __delitem__(self, index): - * self._check_frozen() # <<<<<<<<<<<<<< - * del self._items[index] - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":36 - * def __delitem__(self, index): - * self._check_frozen() - * del self._items[index] # <<<<<<<<<<<<<< - * - * def __len__(self): - */ - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 36, __pyx_L1_error) - } - if (unlikely(PyObject_DelItem(__pyx_v_self->_items, __pyx_v_index) < 0)) __PYX_ERR(0, 36, __pyx_L1_error) - - /* "aiohttp/_frozenlist.pyx":34 - * self._items[index] = value - * - * def __delitem__(self, index): # <<<<<<<<<<<<<< - * self._check_frozen() - * del self._items[index] - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__delitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":38 - * del self._items[index] - * - * def __len__(self): # <<<<<<<<<<<<<< - * return self._fast_len() - * - */ - -/* Python wrapper */ -static Py_ssize_t __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_11__len__(PyObject *__pyx_v_self); /*proto*/ -static Py_ssize_t __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_11__len__(PyObject *__pyx_v_self) { - Py_ssize_t __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__len__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_10__len__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static Py_ssize_t __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_10__len__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - Py_ssize_t __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - Py_ssize_t __pyx_t_2; - __Pyx_RefNannySetupContext("__len__", 0); - - /* "aiohttp/_frozenlist.pyx":39 - * - * def __len__(self): - * return self._fast_len() # <<<<<<<<<<<<<< - * - * def __iter__(self): - */ - __pyx_t_1 = __pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 39, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_t_1); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 39, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_2; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":38 - * del self._items[index] - * - * def __len__(self): # <<<<<<<<<<<<<< - * return self._fast_len() - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__len__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":41 - * return self._fast_len() - * - * def __iter__(self): # <<<<<<<<<<<<<< - * return self._items.__iter__() - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_13__iter__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_13__iter__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__iter__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_12__iter__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_12__iter__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - __Pyx_RefNannySetupContext("__iter__", 0); - - /* "aiohttp/_frozenlist.pyx":42 - * - * def __iter__(self): - * return self._items.__iter__() # <<<<<<<<<<<<<< - * - * def __reversed__(self): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_iter); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 42, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 42, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":41 - * return self._fast_len() - * - * def __iter__(self): # <<<<<<<<<<<<<< - * return self._items.__iter__() - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__iter__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":44 - * return self._items.__iter__() - * - * def __reversed__(self): # <<<<<<<<<<<<<< - * return self._items.__reversed__() - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_15__reversed__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_15__reversed__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__reversed__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_14__reversed__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_14__reversed__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - __Pyx_RefNannySetupContext("__reversed__", 0); - - /* "aiohttp/_frozenlist.pyx":45 - * - * def __reversed__(self): - * return self._items.__reversed__() # <<<<<<<<<<<<<< - * - * def __richcmp__(self, other, op): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_reversed); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 45, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 45, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":44 - * return self._items.__iter__() - * - * def __reversed__(self): # <<<<<<<<<<<<<< - * return self._items.__reversed__() - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__reversed__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":47 - * return self._items.__reversed__() - * - * def __richcmp__(self, other, op): # <<<<<<<<<<<<<< - * if op == 0: # < - * return list(self) < other - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_17__richcmp__(PyObject *__pyx_v_self, PyObject *__pyx_v_other, int __pyx_arg_op); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_17__richcmp__(PyObject *__pyx_v_self, PyObject *__pyx_v_other, int __pyx_arg_op) { - PyObject *__pyx_v_op = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__richcmp__ (wrapper)", 0); - __pyx_v_op = __Pyx_PyInt_From_int(__pyx_arg_op); if (unlikely(!__pyx_v_op)) __PYX_ERR(0, 47, __pyx_L3_error) - __Pyx_GOTREF(__pyx_v_op); - goto __pyx_L4_argument_unpacking_done; - __pyx_L3_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__richcmp__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_16__richcmp__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_other), ((PyObject *)__pyx_v_op)); - - /* function exit code */ - __Pyx_XDECREF(__pyx_v_op); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_16__richcmp__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_other, PyObject *__pyx_v_op) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - __Pyx_RefNannySetupContext("__richcmp__", 0); - - /* "aiohttp/_frozenlist.pyx":48 - * - * def __richcmp__(self, other, op): - * if op == 0: # < # <<<<<<<<<<<<<< - * return list(self) < other - * if op == 1: # <= - */ - __pyx_t_1 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_0, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 48, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 48, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":49 - * def __richcmp__(self, other, op): - * if op == 0: # < - * return list(self) < other # <<<<<<<<<<<<<< - * if op == 1: # <= - * return list(self) <= other - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 49, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_v_other, Py_LT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 49, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":48 - * - * def __richcmp__(self, other, op): - * if op == 0: # < # <<<<<<<<<<<<<< - * return list(self) < other - * if op == 1: # <= - */ - } - - /* "aiohttp/_frozenlist.pyx":50 - * if op == 0: # < - * return list(self) < other - * if op == 1: # <= # <<<<<<<<<<<<<< - * return list(self) <= other - * if op == 2: # == - */ - __pyx_t_3 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_1, 1, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 50, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 50, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":51 - * return list(self) < other - * if op == 1: # <= - * return list(self) <= other # <<<<<<<<<<<<<< - * if op == 2: # == - * return list(self) == other - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 51, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_1 = PyObject_RichCompare(__pyx_t_3, __pyx_v_other, Py_LE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 51, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":50 - * if op == 0: # < - * return list(self) < other - * if op == 1: # <= # <<<<<<<<<<<<<< - * return list(self) <= other - * if op == 2: # == - */ - } - - /* "aiohttp/_frozenlist.pyx":52 - * if op == 1: # <= - * return list(self) <= other - * if op == 2: # == # <<<<<<<<<<<<<< - * return list(self) == other - * if op == 3: # != - */ - __pyx_t_1 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_2, 2, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 52, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 52, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":53 - * return list(self) <= other - * if op == 2: # == - * return list(self) == other # <<<<<<<<<<<<<< - * if op == 3: # != - * return list(self) != other - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 53, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_v_other, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 53, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":52 - * if op == 1: # <= - * return list(self) <= other - * if op == 2: # == # <<<<<<<<<<<<<< - * return list(self) == other - * if op == 3: # != - */ - } - - /* "aiohttp/_frozenlist.pyx":54 - * if op == 2: # == - * return list(self) == other - * if op == 3: # != # <<<<<<<<<<<<<< - * return list(self) != other - * if op == 4: # > - */ - __pyx_t_3 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_3, 3, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 54, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":55 - * return list(self) == other - * if op == 3: # != - * return list(self) != other # <<<<<<<<<<<<<< - * if op == 4: # > - * return list(self) > other - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 55, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_1 = PyObject_RichCompare(__pyx_t_3, __pyx_v_other, Py_NE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 55, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":54 - * if op == 2: # == - * return list(self) == other - * if op == 3: # != # <<<<<<<<<<<<<< - * return list(self) != other - * if op == 4: # > - */ - } - - /* "aiohttp/_frozenlist.pyx":56 - * if op == 3: # != - * return list(self) != other - * if op == 4: # > # <<<<<<<<<<<<<< - * return list(self) > other - * if op == 5: # => - */ - __pyx_t_1 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_4, 4, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 56, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 56, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":57 - * return list(self) != other - * if op == 4: # > - * return list(self) > other # <<<<<<<<<<<<<< - * if op == 5: # => - * return list(self) >= other - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 57, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_v_other, Py_GT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 57, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":56 - * if op == 3: # != - * return list(self) != other - * if op == 4: # > # <<<<<<<<<<<<<< - * return list(self) > other - * if op == 5: # => - */ - } - - /* "aiohttp/_frozenlist.pyx":58 - * if op == 4: # > - * return list(self) > other - * if op == 5: # => # <<<<<<<<<<<<<< - * return list(self) >= other - * - */ - __pyx_t_3 = __Pyx_PyInt_EqObjC(__pyx_v_op, __pyx_int_5, 5, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 58, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 58, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (__pyx_t_2) { - - /* "aiohttp/_frozenlist.pyx":59 - * return list(self) > other - * if op == 5: # => - * return list(self) >= other # <<<<<<<<<<<<<< - * - * def insert(self, pos, item): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = PySequence_List(((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 59, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_1 = PyObject_RichCompare(__pyx_t_3, __pyx_v_other, Py_GE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 59, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":58 - * if op == 4: # > - * return list(self) > other - * if op == 5: # => # <<<<<<<<<<<<<< - * return list(self) >= other - * - */ - } - - /* "aiohttp/_frozenlist.pyx":47 - * return self._items.__reversed__() - * - * def __richcmp__(self, other, op): # <<<<<<<<<<<<<< - * if op == 0: # < - * return list(self) < other - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__richcmp__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":61 - * return list(self) >= other - * - * def insert(self, pos, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.insert(pos, item) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_19insert(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_19insert(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_pos = 0; - PyObject *__pyx_v_item = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("insert (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pos,&__pyx_n_s_item,0}; - PyObject* values[2] = {0,0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pos)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_item)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("insert", 1, 2, 2, 1); __PYX_ERR(0, 61, __pyx_L3_error) - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "insert") < 0)) __PYX_ERR(0, 61, __pyx_L3_error) - } - } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { - goto __pyx_L5_argtuple_error; - } else { - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - } - __pyx_v_pos = values[0]; - __pyx_v_item = values[1]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("insert", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 61, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.insert", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_18insert(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), __pyx_v_pos, __pyx_v_item); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_18insert(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_pos, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - Py_ssize_t __pyx_t_2; - int __pyx_t_3; - __Pyx_RefNannySetupContext("insert", 0); - - /* "aiohttp/_frozenlist.pyx":62 - * - * def insert(self, pos, item): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items.insert(pos, item) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 62, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":63 - * def insert(self, pos, item): - * self._check_frozen() - * self._items.insert(pos, item) # <<<<<<<<<<<<<< - * - * def __contains__(self, item): - */ - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "insert"); - __PYX_ERR(0, 63, __pyx_L1_error) - } - __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_v_pos); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 63, __pyx_L1_error) - __pyx_t_3 = PyList_Insert(__pyx_v_self->_items, __pyx_t_2, __pyx_v_item); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(0, 63, __pyx_L1_error) - - /* "aiohttp/_frozenlist.pyx":61 - * return list(self) >= other - * - * def insert(self, pos, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.insert(pos, item) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.insert", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":65 - * self._items.insert(pos, item) - * - * def __contains__(self, item): # <<<<<<<<<<<<<< - * return item in self._items - * - */ - -/* Python wrapper */ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_21__contains__(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static int __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_21__contains__(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__contains__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_20__contains__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_20__contains__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item) { - int __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - __Pyx_RefNannySetupContext("__contains__", 0); - - /* "aiohttp/_frozenlist.pyx":66 - * - * def __contains__(self, item): - * return item in self._items # <<<<<<<<<<<<<< - * - * def __iadd__(self, items): - */ - __pyx_t_1 = (__Pyx_PySequence_ContainsTF(__pyx_v_item, __pyx_v_self->_items, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 66, __pyx_L1_error) - __pyx_r = __pyx_t_1; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":65 - * self._items.insert(pos, item) - * - * def __contains__(self, item): # <<<<<<<<<<<<<< - * return item in self._items - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__contains__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":68 - * return item in self._items - * - * def __iadd__(self, items): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items += list(items) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_23__iadd__(PyObject *__pyx_v_self, PyObject *__pyx_v_items); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_23__iadd__(PyObject *__pyx_v_self, PyObject *__pyx_v_items) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__iadd__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_22__iadd__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_items)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_22__iadd__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - __Pyx_RefNannySetupContext("__iadd__", 0); - - /* "aiohttp/_frozenlist.pyx":69 - * - * def __iadd__(self, items): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items += list(items) - * return self - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 69, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":70 - * def __iadd__(self, items): - * self._check_frozen() - * self._items += list(items) # <<<<<<<<<<<<<< - * return self - * - */ - __pyx_t_1 = PySequence_List(__pyx_v_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 70, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_self->_items, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 70, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_GIVEREF(__pyx_t_2); - __Pyx_GOTREF(__pyx_v_self->_items); - __Pyx_DECREF(__pyx_v_self->_items); - __pyx_v_self->_items = ((PyObject*)__pyx_t_2); - __pyx_t_2 = 0; - - /* "aiohttp/_frozenlist.pyx":71 - * self._check_frozen() - * self._items += list(items) - * return self # <<<<<<<<<<<<<< - * - * def index(self, item): - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(((PyObject *)__pyx_v_self)); - __pyx_r = ((PyObject *)__pyx_v_self); - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":68 - * return item in self._items - * - * def __iadd__(self, items): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items += list(items) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__iadd__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":73 - * return self - * - * def index(self, item): # <<<<<<<<<<<<<< - * return self._items.index(item) - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_25index(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_25index(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("index (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_24index(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_24index(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - __Pyx_RefNannySetupContext("index", 0); - - /* "aiohttp/_frozenlist.pyx":74 - * - * def index(self, item): - * return self._items.index(item) # <<<<<<<<<<<<<< - * - * def remove(self, item): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_index); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 74, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_item) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_item); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 74, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":73 - * return self - * - * def index(self, item): # <<<<<<<<<<<<<< - * return self._items.index(item) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.index", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":76 - * return self._items.index(item) - * - * def remove(self, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.remove(item) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_27remove(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_27remove(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("remove (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_26remove(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_26remove(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - __Pyx_RefNannySetupContext("remove", 0); - - /* "aiohttp/_frozenlist.pyx":77 - * - * def remove(self, item): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items.remove(item) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 77, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":78 - * def remove(self, item): - * self._check_frozen() - * self._items.remove(item) # <<<<<<<<<<<<<< - * - * def clear(self): - */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_remove); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 78, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_item) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_item); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 78, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":76 - * return self._items.index(item) - * - * def remove(self, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.remove(item) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.remove", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":80 - * self._items.remove(item) - * - * def clear(self): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.clear() - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_29clear(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_29clear(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("clear (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_28clear(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_28clear(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - __Pyx_RefNannySetupContext("clear", 0); - - /* "aiohttp/_frozenlist.pyx":81 - * - * def clear(self): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items.clear() - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 81, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":82 - * def clear(self): - * self._check_frozen() - * self._items.clear() # <<<<<<<<<<<<<< - * - * def extend(self, items): - */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_clear); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 82, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 82, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":80 - * self._items.remove(item) - * - * def clear(self): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.clear() - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.clear", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":84 - * self._items.clear() - * - * def extend(self, items): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items += list(items) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_31extend(PyObject *__pyx_v_self, PyObject *__pyx_v_items); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_31extend(PyObject *__pyx_v_self, PyObject *__pyx_v_items) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("extend (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_30extend(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_items)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_30extend(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_items) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - __Pyx_RefNannySetupContext("extend", 0); - - /* "aiohttp/_frozenlist.pyx":85 - * - * def extend(self, items): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items += list(items) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 85, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":86 - * def extend(self, items): - * self._check_frozen() - * self._items += list(items) # <<<<<<<<<<<<<< - * - * def reverse(self): - */ - __pyx_t_1 = PySequence_List(__pyx_v_items); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 86, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_self->_items, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 86, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_GIVEREF(__pyx_t_2); - __Pyx_GOTREF(__pyx_v_self->_items); - __Pyx_DECREF(__pyx_v_self->_items); - __pyx_v_self->_items = ((PyObject*)__pyx_t_2); - __pyx_t_2 = 0; - - /* "aiohttp/_frozenlist.pyx":84 - * self._items.clear() - * - * def extend(self, items): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items += list(items) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.extend", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":88 - * self._items += list(items) - * - * def reverse(self): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.reverse() - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_33reverse(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_33reverse(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("reverse (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_32reverse(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_32reverse(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - __Pyx_RefNannySetupContext("reverse", 0); - - /* "aiohttp/_frozenlist.pyx":89 - * - * def reverse(self): - * self._check_frozen() # <<<<<<<<<<<<<< - * self._items.reverse() - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 89, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":90 - * def reverse(self): - * self._check_frozen() - * self._items.reverse() # <<<<<<<<<<<<<< - * - * def pop(self, index=-1): - */ - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "reverse"); - __PYX_ERR(0, 90, __pyx_L1_error) - } - __pyx_t_2 = PyList_Reverse(__pyx_v_self->_items); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(0, 90, __pyx_L1_error) - - /* "aiohttp/_frozenlist.pyx":88 - * self._items += list(items) - * - * def reverse(self): # <<<<<<<<<<<<<< - * self._check_frozen() - * self._items.reverse() - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.reverse", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":92 - * self._items.reverse() - * - * def pop(self, index=-1): # <<<<<<<<<<<<<< - * self._check_frozen() - * return self._items.pop(index) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_35pop(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_35pop(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_index = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("pop (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_index,0}; - PyObject* values[1] = {0}; - values[0] = ((PyObject *)__pyx_int_neg_1); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (kw_args > 0) { - PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_index); - if (value) { values[0] = value; kw_args--; } - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "pop") < 0)) __PYX_ERR(0, 92, __pyx_L3_error) - } - } else { - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - } - __pyx_v_index = values[0]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("pop", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 92, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.pop", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_34pop(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), __pyx_v_index); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_34pop(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_index) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - Py_ssize_t __pyx_t_2; - __Pyx_RefNannySetupContext("pop", 0); - - /* "aiohttp/_frozenlist.pyx":93 - * - * def pop(self, index=-1): - * self._check_frozen() # <<<<<<<<<<<<<< - * return self._items.pop(index) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 93, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":94 - * def pop(self, index=-1): - * self._check_frozen() - * return self._items.pop(index) # <<<<<<<<<<<<<< - * - * def append(self, item): - */ - __Pyx_XDECREF(__pyx_r); - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "pop"); - __PYX_ERR(0, 94, __pyx_L1_error) - } - __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_v_index); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 94, __pyx_L1_error) - __pyx_t_1 = __Pyx_PyList_PopIndex(__pyx_v_self->_items, __pyx_v_index, __pyx_t_2, 1, Py_ssize_t, PyInt_FromSsize_t); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 94, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":92 - * self._items.reverse() - * - * def pop(self, index=-1): # <<<<<<<<<<<<<< - * self._check_frozen() - * return self._items.pop(index) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.pop", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":96 - * return self._items.pop(index) - * - * def append(self, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * return self._items.append(item) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_37append(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_37append(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("append (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_36append(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_36append(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - __Pyx_RefNannySetupContext("append", 0); - - /* "aiohttp/_frozenlist.pyx":97 - * - * def append(self, item): - * self._check_frozen() # <<<<<<<<<<<<<< - * return self._items.append(item) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self->__pyx_vtab)->_check_frozen(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 97, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "aiohttp/_frozenlist.pyx":98 - * def append(self, item): - * self._check_frozen() - * return self._items.append(item) # <<<<<<<<<<<<<< - * - * def count(self, item): - */ - __Pyx_XDECREF(__pyx_r); - if (unlikely(__pyx_v_self->_items == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "append"); - __PYX_ERR(0, 98, __pyx_L1_error) - } - __pyx_t_2 = __Pyx_PyList_Append(__pyx_v_self->_items, __pyx_v_item); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(0, 98, __pyx_L1_error) - __pyx_t_1 = __Pyx_Owned_Py_None(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 98, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":96 - * return self._items.pop(index) - * - * def append(self, item): # <<<<<<<<<<<<<< - * self._check_frozen() - * return self._items.append(item) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.append", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":100 - * return self._items.append(item) - * - * def count(self, item): # <<<<<<<<<<<<<< - * return self._items.count(item) - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_39count(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_39count(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("count (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_38count(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_38count(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - __Pyx_RefNannySetupContext("count", 0); - - /* "aiohttp/_frozenlist.pyx":101 - * - * def count(self, item): - * return self._items.count(item) # <<<<<<<<<<<<<< - * - * def __repr__(self): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_items, __pyx_n_s_count); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 101, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_item) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_item); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 101, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":100 - * return self._items.append(item) - * - * def count(self, item): # <<<<<<<<<<<<<< - * return self._items.count(item) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.count", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":103 - * return self._items.count(item) - * - * def __repr__(self): # <<<<<<<<<<<<<< - * return ''.format(self.frozen, - * self._items) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_41__repr__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_41__repr__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_40__repr__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_40__repr__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - int __pyx_t_5; - PyObject *__pyx_t_6 = NULL; - __Pyx_RefNannySetupContext("__repr__", 0); - - /* "aiohttp/_frozenlist.pyx":104 - * - * def __repr__(self): - * return ''.format(self.frozen, # <<<<<<<<<<<<<< - * self._items) - * - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_kp_u_FrozenList_frozen_r, __pyx_n_s_format); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyBool_FromLong(__pyx_v_self->frozen); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - - /* "aiohttp/_frozenlist.pyx":105 - * def __repr__(self): - * return ''.format(self.frozen, - * self._items) # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_4 = NULL; - __pyx_t_5 = 0; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - __pyx_t_5 = 1; - } - } - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(__pyx_t_2)) { - PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_t_3, __pyx_v_self->_items}; - __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } else - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) { - PyObject *__pyx_temp[3] = {__pyx_t_4, __pyx_t_3, __pyx_v_self->_items}; - __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_5, 2+__pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } else - #endif - { - __pyx_t_6 = PyTuple_New(2+__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - if (__pyx_t_4) { - __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); __pyx_t_4 = NULL; - } - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_5, __pyx_t_3); - __Pyx_INCREF(__pyx_v_self->_items); - __Pyx_GIVEREF(__pyx_v_self->_items); - PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_5, __pyx_v_self->_items); - __pyx_t_3 = 0; - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_6, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 104, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - } - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "aiohttp/_frozenlist.pyx":103 - * return self._items.count(item) - * - * def __repr__(self): # <<<<<<<<<<<<<< - * return ''.format(self.frozen, - * self._items) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "aiohttp/_frozenlist.pyx":6 - * cdef class FrozenList: - * - * cdef readonly bint frozen # <<<<<<<<<<<<<< - * cdef list _items - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_6frozen_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_6frozen_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6frozen___get__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_6frozen___get__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - __Pyx_RefNannySetupContext("__get__", 0); - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->frozen); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.frozen.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * cdef tuple state - * cdef object _dict - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_43__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_43__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_42__reduce_cython__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_42__reduce_cython__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self) { - PyObject *__pyx_v_state = 0; - PyObject *__pyx_v__dict = 0; - int __pyx_v_use_setstate; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_t_3; - int __pyx_t_4; - PyObject *__pyx_t_5 = NULL; - __Pyx_RefNannySetupContext("__reduce_cython__", 0); - - /* "(tree fragment)":5 - * cdef object _dict - * cdef bint use_setstate - * state = (self._items, self.frozen) # <<<<<<<<<<<<<< - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: - */ - __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->frozen); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_v_self->_items); - __Pyx_GIVEREF(__pyx_v_self->_items); - PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_self->_items); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1); - __pyx_t_1 = 0; - __pyx_v_state = ((PyObject*)__pyx_t_2); - __pyx_t_2 = 0; - - /* "(tree fragment)":6 - * cdef bint use_setstate - * state = (self._items, self.frozen) - * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< - * if _dict is not None: - * state += (_dict,) - */ - __pyx_t_2 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_v__dict = __pyx_t_2; - __pyx_t_2 = 0; - - /* "(tree fragment)":7 - * state = (self._items, self.frozen) - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: # <<<<<<<<<<<<<< - * state += (_dict,) - * use_setstate = True - */ - __pyx_t_3 = (__pyx_v__dict != Py_None); - __pyx_t_4 = (__pyx_t_3 != 0); - if (__pyx_t_4) { - - /* "(tree fragment)":8 - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: - * state += (_dict,) # <<<<<<<<<<<<<< - * use_setstate = True - * else: - */ - __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 8, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_v__dict); - __Pyx_GIVEREF(__pyx_v__dict); - PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v__dict); - __pyx_t_1 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_1)); - __pyx_t_1 = 0; - - /* "(tree fragment)":9 - * if _dict is not None: - * state += (_dict,) - * use_setstate = True # <<<<<<<<<<<<<< - * else: - * use_setstate = self._items is not None - */ - __pyx_v_use_setstate = 1; - - /* "(tree fragment)":7 - * state = (self._items, self.frozen) - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: # <<<<<<<<<<<<<< - * state += (_dict,) - * use_setstate = True - */ - goto __pyx_L3; - } - - /* "(tree fragment)":11 - * use_setstate = True - * else: - * use_setstate = self._items is not None # <<<<<<<<<<<<<< - * if use_setstate: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, None), state - */ - /*else*/ { - __pyx_t_4 = (__pyx_v_self->_items != ((PyObject*)Py_None)); - __pyx_v_use_setstate = __pyx_t_4; - } - __pyx_L3:; - - /* "(tree fragment)":12 - * else: - * use_setstate = self._items is not None - * if use_setstate: # <<<<<<<<<<<<<< - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, None), state - * else: - */ - __pyx_t_4 = (__pyx_v_use_setstate != 0); - if (__pyx_t_4) { - - /* "(tree fragment)":13 - * use_setstate = self._items is not None - * if use_setstate: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, None), state # <<<<<<<<<<<<<< - * else: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, state) - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_pyx_unpickle_FrozenList); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 13, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_INCREF(__pyx_int_155820355); - __Pyx_GIVEREF(__pyx_int_155820355); - PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_155820355); - __Pyx_INCREF(Py_None); - __Pyx_GIVEREF(Py_None); - PyTuple_SET_ITEM(__pyx_t_2, 2, Py_None); - __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 13, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_2); - __Pyx_INCREF(__pyx_v_state); - __Pyx_GIVEREF(__pyx_v_state); - PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_state); - __pyx_t_1 = 0; - __pyx_t_2 = 0; - __pyx_r = __pyx_t_5; - __pyx_t_5 = 0; - goto __pyx_L0; - - /* "(tree fragment)":12 - * else: - * use_setstate = self._items is not None - * if use_setstate: # <<<<<<<<<<<<<< - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, None), state - * else: - */ - } - - /* "(tree fragment)":15 - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, None), state - * else: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, state) # <<<<<<<<<<<<<< - * def __setstate_cython__(self, __pyx_state): - * __pyx_unpickle_FrozenList__set_state(self, __pyx_state) - */ - /*else*/ { - __Pyx_XDECREF(__pyx_r); - __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_pyx_unpickle_FrozenList); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_INCREF(__pyx_int_155820355); - __Pyx_GIVEREF(__pyx_int_155820355); - PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_155820355); - __Pyx_INCREF(__pyx_v_state); - __Pyx_GIVEREF(__pyx_v_state); - PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_v_state); - __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_2); - __pyx_t_5 = 0; - __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - } - - /* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * cdef tuple state - * cdef object _dict - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_state); - __Pyx_XDECREF(__pyx_v__dict); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":16 - * else: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, state) - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * __pyx_unpickle_FrozenList__set_state(self, __pyx_state) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_45__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_45__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist_10FrozenList_44__setstate_cython__(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist_10FrozenList_44__setstate_cython__(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v_self, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - __Pyx_RefNannySetupContext("__setstate_cython__", 0); - - /* "(tree fragment)":17 - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, state) - * def __setstate_cython__(self, __pyx_state): - * __pyx_unpickle_FrozenList__set_state(self, __pyx_state) # <<<<<<<<<<<<<< - */ - if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error) - __pyx_t_1 = __pyx_f_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "(tree fragment)":16 - * else: - * return __pyx_unpickle_FrozenList, (type(self), 0x949a143, state) - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * __pyx_unpickle_FrozenList__set_state(self, __pyx_state) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("aiohttp._frozenlist.FrozenList.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":1 - * def __pyx_unpickle_FrozenList(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_1__pyx_unpickle_FrozenList(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static PyMethodDef __pyx_mdef_7aiohttp_11_frozenlist_1__pyx_unpickle_FrozenList = {"__pyx_unpickle_FrozenList", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_11_frozenlist_1__pyx_unpickle_FrozenList, METH_VARARGS|METH_KEYWORDS, 0}; -static PyObject *__pyx_pw_7aiohttp_11_frozenlist_1__pyx_unpickle_FrozenList(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v___pyx_type = 0; - long __pyx_v___pyx_checksum; - PyObject *__pyx_v___pyx_state = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__pyx_unpickle_FrozenList (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; - PyObject* values[3] = {0,0,0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - CYTHON_FALLTHROUGH; - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_FrozenList", 1, 3, 3, 1); __PYX_ERR(1, 1, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 2: - if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_FrozenList", 1, 3, 3, 2); __PYX_ERR(1, 1, __pyx_L3_error) - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_FrozenList") < 0)) __PYX_ERR(1, 1, __pyx_L3_error) - } - } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { - goto __pyx_L5_argtuple_error; - } else { - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - } - __pyx_v___pyx_type = values[0]; - __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(1, 1, __pyx_L3_error) - __pyx_v___pyx_state = values[2]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_FrozenList", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(1, 1, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("aiohttp._frozenlist.__pyx_unpickle_FrozenList", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_v___pyx_PickleError = 0; - PyObject *__pyx_v___pyx_result = 0; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - int __pyx_t_6; - __Pyx_RefNannySetupContext("__pyx_unpickle_FrozenList", 0); - - /* "(tree fragment)":4 - * cdef object __pyx_PickleError - * cdef object __pyx_result - * if __pyx_checksum != 0x949a143: # <<<<<<<<<<<<<< - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - */ - __pyx_t_1 = ((__pyx_v___pyx_checksum != 0x949a143) != 0); - if (__pyx_t_1) { - - /* "(tree fragment)":5 - * cdef object __pyx_result - * if __pyx_checksum != 0x949a143: - * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - * __pyx_result = FrozenList.__new__(__pyx_type) - */ - __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_n_s_PickleError); - __Pyx_GIVEREF(__pyx_n_s_PickleError); - PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_PickleError); - __pyx_t_3 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_t_2); - __pyx_v___pyx_PickleError = __pyx_t_2; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "(tree fragment)":6 - * if __pyx_checksum != 0x949a143: - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) # <<<<<<<<<<<<<< - * __pyx_result = FrozenList.__new__(__pyx_type) - * if __pyx_state is not None: - */ - __pyx_t_2 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_s_vs_0x94, __pyx_t_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_INCREF(__pyx_v___pyx_PickleError); - __pyx_t_2 = __pyx_v___pyx_PickleError; __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(1, 6, __pyx_L1_error) - - /* "(tree fragment)":4 - * cdef object __pyx_PickleError - * cdef object __pyx_result - * if __pyx_checksum != 0x949a143: # <<<<<<<<<<<<<< - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - */ - } - - /* "(tree fragment)":7 - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - * __pyx_result = FrozenList.__new__(__pyx_type) # <<<<<<<<<<<<<< - * if __pyx_state is not None: - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_ptype_7aiohttp_11_frozenlist_FrozenList), __pyx_n_s_new); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v___pyx_type); - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_v___pyx_result = __pyx_t_3; - __pyx_t_3 = 0; - - /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - * __pyx_result = FrozenList.__new__(__pyx_type) - * if __pyx_state is not None: # <<<<<<<<<<<<<< - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - * return __pyx_result - */ - __pyx_t_1 = (__pyx_v___pyx_state != Py_None); - __pyx_t_6 = (__pyx_t_1 != 0); - if (__pyx_t_6) { - - /* "(tree fragment)":9 - * __pyx_result = FrozenList.__new__(__pyx_type) - * if __pyx_state is not None: - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< - * return __pyx_result - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): - */ - if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 9, __pyx_L1_error) - __pyx_t_3 = __pyx_f_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList__set_state(((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 9, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (%s vs 0x949a143 = (_items, frozen))" % __pyx_checksum) - * __pyx_result = FrozenList.__new__(__pyx_type) - * if __pyx_state is not None: # <<<<<<<<<<<<<< - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - * return __pyx_result - */ - } - - /* "(tree fragment)":10 - * if __pyx_state is not None: - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - * return __pyx_result # <<<<<<<<<<<<<< - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v___pyx_result); - __pyx_r = __pyx_v___pyx_result; - goto __pyx_L0; - - /* "(tree fragment)":1 - * def __pyx_unpickle_FrozenList(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("aiohttp._frozenlist.__pyx_unpickle_FrozenList", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v___pyx_PickleError); - __Pyx_XDECREF(__pyx_v___pyx_result); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":11 - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - * return __pyx_result - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): - */ - -static PyObject *__pyx_f_7aiohttp_11_frozenlist___pyx_unpickle_FrozenList__set_state(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - Py_ssize_t __pyx_t_3; - int __pyx_t_4; - int __pyx_t_5; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - __Pyx_RefNannySetupContext("__pyx_unpickle_FrozenList__set_state", 0); - - /* "(tree fragment)":12 - * return __pyx_result - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] # <<<<<<<<<<<<<< - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): - * __pyx_result.__dict__.update(__pyx_state[2]) - */ - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(1, 12, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (!(likely(PyList_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "list", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(1, 12, __pyx_L1_error) - __Pyx_GIVEREF(__pyx_t_1); - __Pyx_GOTREF(__pyx_v___pyx_result->_items); - __Pyx_DECREF(__pyx_v___pyx_result->_items); - __pyx_v___pyx_result->_items = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(1, 12, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 12, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 12, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_v___pyx_result->frozen = __pyx_t_2; - - /* "(tree fragment)":13 - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< - * __pyx_result.__dict__.update(__pyx_state[2]) - */ - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(1, 13, __pyx_L1_error) - } - __pyx_t_3 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1))) __PYX_ERR(1, 13, __pyx_L1_error) - __pyx_t_4 = ((__pyx_t_3 > 2) != 0); - if (__pyx_t_4) { - } else { - __pyx_t_2 = __pyx_t_4; - goto __pyx_L4_bool_binop_done; - } - __pyx_t_4 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 13, __pyx_L1_error) - __pyx_t_5 = (__pyx_t_4 != 0); - __pyx_t_2 = __pyx_t_5; - __pyx_L4_bool_binop_done:; - if (__pyx_t_2) { - - /* "(tree fragment)":14 - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): - * __pyx_result.__dict__.update(__pyx_state[2]) # <<<<<<<<<<<<<< - */ - __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_update); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(1, 14, __pyx_L1_error) - } - __pyx_t_6 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_8 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { - __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); - if (likely(__pyx_t_8)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); - __Pyx_INCREF(__pyx_t_8); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_7, function); - } - } - __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_6); - __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "(tree fragment)":13 - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< - * __pyx_result.__dict__.update(__pyx_state[2]) - */ - } - - /* "(tree fragment)":11 - * __pyx_unpickle_FrozenList__set_state( __pyx_result, __pyx_state) - * return __pyx_result - * cdef __pyx_unpickle_FrozenList__set_state(FrozenList __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< - * __pyx_result._items = __pyx_state[0]; __pyx_result.frozen = __pyx_state[1] - * if len(__pyx_state) > 2 and hasattr(__pyx_result, '__dict__'): - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_AddTraceback("aiohttp._frozenlist.__pyx_unpickle_FrozenList__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} -static struct __pyx_vtabstruct_7aiohttp_11_frozenlist_FrozenList __pyx_vtable_7aiohttp_11_frozenlist_FrozenList; - -static PyObject *__pyx_tp_new_7aiohttp_11_frozenlist_FrozenList(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { - struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *p; - PyObject *o; - if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { - o = (*t->tp_alloc)(t, 0); - } else { - o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); - } - if (unlikely(!o)) return 0; - p = ((struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)o); - p->__pyx_vtab = __pyx_vtabptr_7aiohttp_11_frozenlist_FrozenList; - p->_items = ((PyObject*)Py_None); Py_INCREF(Py_None); - return o; -} - -static void __pyx_tp_dealloc_7aiohttp_11_frozenlist_FrozenList(PyObject *o) { - struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *p = (struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)o; - #if CYTHON_USE_TP_FINALIZE - if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { - if (PyObject_CallFinalizerFromDealloc(o)) return; - } - #endif - PyObject_GC_UnTrack(o); - Py_CLEAR(p->_items); - (*Py_TYPE(o)->tp_free)(o); -} - -static int __pyx_tp_traverse_7aiohttp_11_frozenlist_FrozenList(PyObject *o, visitproc v, void *a) { - int e; - struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *p = (struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)o; - if (p->_items) { - e = (*v)(p->_items, a); if (e) return e; - } - return 0; -} - -static int __pyx_tp_clear_7aiohttp_11_frozenlist_FrozenList(PyObject *o) { - PyObject* tmp; - struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *p = (struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *)o; - tmp = ((PyObject*)p->_items); - p->_items = ((PyObject*)Py_None); Py_INCREF(Py_None); - Py_XDECREF(tmp); - return 0; -} -static PyObject *__pyx_sq_item_7aiohttp_11_frozenlist_FrozenList(PyObject *o, Py_ssize_t i) { - PyObject *r; - PyObject *x = PyInt_FromSsize_t(i); if(!x) return 0; - r = Py_TYPE(o)->tp_as_mapping->mp_subscript(o, x); - Py_DECREF(x); - return r; -} - -static int __pyx_mp_ass_subscript_7aiohttp_11_frozenlist_FrozenList(PyObject *o, PyObject *i, PyObject *v) { - if (v) { - return __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_7__setitem__(o, i, v); - } - else { - return __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_9__delitem__(o, i); - } -} - -static PyObject *__pyx_getprop_7aiohttp_11_frozenlist_10FrozenList_frozen(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_6frozen_1__get__(o); -} - -static PyMethodDef __pyx_methods_7aiohttp_11_frozenlist_FrozenList[] = { - {"freeze", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_3freeze, METH_NOARGS, 0}, - {"__reversed__", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_15__reversed__, METH_NOARGS, 0}, - {"insert", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_19insert, METH_VARARGS|METH_KEYWORDS, 0}, - {"index", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_25index, METH_O, 0}, - {"remove", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_27remove, METH_O, 0}, - {"clear", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_29clear, METH_NOARGS, 0}, - {"extend", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_31extend, METH_O, 0}, - {"reverse", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_33reverse, METH_NOARGS, 0}, - {"pop", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_35pop, METH_VARARGS|METH_KEYWORDS, 0}, - {"append", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_37append, METH_O, 0}, - {"count", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_39count, METH_O, 0}, - {"__reduce_cython__", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_43__reduce_cython__, METH_NOARGS, 0}, - {"__setstate_cython__", (PyCFunction)__pyx_pw_7aiohttp_11_frozenlist_10FrozenList_45__setstate_cython__, METH_O, 0}, - {0, 0, 0, 0} -}; - -static struct PyGetSetDef __pyx_getsets_7aiohttp_11_frozenlist_FrozenList[] = { - {(char *)"frozen", __pyx_getprop_7aiohttp_11_frozenlist_10FrozenList_frozen, 0, (char *)0, 0}, - {0, 0, 0, 0, 0} -}; - -static PyNumberMethods __pyx_tp_as_number_FrozenList = { - 0, /*nb_add*/ - 0, /*nb_subtract*/ - 0, /*nb_multiply*/ - #if PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000) - 0, /*nb_divide*/ - #endif - 0, /*nb_remainder*/ - 0, /*nb_divmod*/ - 0, /*nb_power*/ - 0, /*nb_negative*/ - 0, /*nb_positive*/ - 0, /*nb_absolute*/ - 0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ - #if PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000) - 0, /*nb_coerce*/ - #endif - 0, /*nb_int*/ - #if PY_MAJOR_VERSION < 3 - 0, /*nb_long*/ - #else - 0, /*reserved*/ - #endif - 0, /*nb_float*/ - #if PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000) - 0, /*nb_oct*/ - #endif - #if PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000) - 0, /*nb_hex*/ - #endif - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_23__iadd__, /*nb_inplace_add*/ - 0, /*nb_inplace_subtract*/ - 0, /*nb_inplace_multiply*/ - #if PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03050000) - 0, /*nb_inplace_divide*/ - #endif - 0, /*nb_inplace_remainder*/ - 0, /*nb_inplace_power*/ - 0, /*nb_inplace_lshift*/ - 0, /*nb_inplace_rshift*/ - 0, /*nb_inplace_and*/ - 0, /*nb_inplace_xor*/ - 0, /*nb_inplace_or*/ - 0, /*nb_floor_divide*/ - 0, /*nb_true_divide*/ - 0, /*nb_inplace_floor_divide*/ - 0, /*nb_inplace_true_divide*/ - 0, /*nb_index*/ - #if PY_VERSION_HEX >= 0x03050000 - 0, /*nb_matrix_multiply*/ - #endif - #if PY_VERSION_HEX >= 0x03050000 - 0, /*nb_inplace_matrix_multiply*/ - #endif -}; - -static PySequenceMethods __pyx_tp_as_sequence_FrozenList = { - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_11__len__, /*sq_length*/ - 0, /*sq_concat*/ - 0, /*sq_repeat*/ - __pyx_sq_item_7aiohttp_11_frozenlist_FrozenList, /*sq_item*/ - 0, /*sq_slice*/ - 0, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_21__contains__, /*sq_contains*/ - 0, /*sq_inplace_concat*/ - 0, /*sq_inplace_repeat*/ -}; - -static PyMappingMethods __pyx_tp_as_mapping_FrozenList = { - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_11__len__, /*mp_length*/ - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_5__getitem__, /*mp_subscript*/ - __pyx_mp_ass_subscript_7aiohttp_11_frozenlist_FrozenList, /*mp_ass_subscript*/ -}; - -static PyTypeObject __pyx_type_7aiohttp_11_frozenlist_FrozenList = { - PyVarObject_HEAD_INIT(0, 0) - "aiohttp._frozenlist.FrozenList", /*tp_name*/ - sizeof(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - __pyx_tp_dealloc_7aiohttp_11_frozenlist_FrozenList, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - #if PY_MAJOR_VERSION < 3 - 0, /*tp_compare*/ - #endif - #if PY_MAJOR_VERSION >= 3 - 0, /*tp_as_async*/ - #endif - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_41__repr__, /*tp_repr*/ - &__pyx_tp_as_number_FrozenList, /*tp_as_number*/ - &__pyx_tp_as_sequence_FrozenList, /*tp_as_sequence*/ - &__pyx_tp_as_mapping_FrozenList, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - 0, /*tp_doc*/ - __pyx_tp_traverse_7aiohttp_11_frozenlist_FrozenList, /*tp_traverse*/ - __pyx_tp_clear_7aiohttp_11_frozenlist_FrozenList, /*tp_clear*/ - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_17__richcmp__, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_13__iter__, /*tp_iter*/ - 0, /*tp_iternext*/ - __pyx_methods_7aiohttp_11_frozenlist_FrozenList, /*tp_methods*/ - 0, /*tp_members*/ - __pyx_getsets_7aiohttp_11_frozenlist_FrozenList, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - __pyx_pw_7aiohttp_11_frozenlist_10FrozenList_1__init__, /*tp_init*/ - 0, /*tp_alloc*/ - __pyx_tp_new_7aiohttp_11_frozenlist_FrozenList, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ - 0, /*tp_bases*/ - 0, /*tp_mro*/ - 0, /*tp_cache*/ - 0, /*tp_subclasses*/ - 0, /*tp_weaklist*/ - 0, /*tp_del*/ - 0, /*tp_version_tag*/ - #if PY_VERSION_HEX >= 0x030400a1 - 0, /*tp_finalize*/ - #endif - #if PY_VERSION_HEX >= 0x030800b1 - 0, /*tp_vectorcall*/ - #endif -}; - -static PyMethodDef __pyx_methods[] = { - {0, 0, 0, 0} -}; - -#if PY_MAJOR_VERSION >= 3 -#if CYTHON_PEP489_MULTI_PHASE_INIT -static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ -static int __pyx_pymod_exec__frozenlist(PyObject* module); /*proto*/ -static PyModuleDef_Slot __pyx_moduledef_slots[] = { - {Py_mod_create, (void*)__pyx_pymod_create}, - {Py_mod_exec, (void*)__pyx_pymod_exec__frozenlist}, - {0, NULL} -}; -#endif - -static struct PyModuleDef __pyx_moduledef = { - PyModuleDef_HEAD_INIT, - "_frozenlist", - 0, /* m_doc */ - #if CYTHON_PEP489_MULTI_PHASE_INIT - 0, /* m_size */ - #else - -1, /* m_size */ - #endif - __pyx_methods /* m_methods */, - #if CYTHON_PEP489_MULTI_PHASE_INIT - __pyx_moduledef_slots, /* m_slots */ - #else - NULL, /* m_reload */ - #endif - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL /* m_free */ -}; -#endif -#ifndef CYTHON_SMALL_CODE -#if defined(__clang__) - #define CYTHON_SMALL_CODE -#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) - #define CYTHON_SMALL_CODE __attribute__((cold)) -#else - #define CYTHON_SMALL_CODE -#endif -#endif - -static __Pyx_StringTabEntry __pyx_string_tab[] = { - {&__pyx_kp_u_Cannot_modify_frozen_list, __pyx_k_Cannot_modify_frozen_list, sizeof(__pyx_k_Cannot_modify_frozen_list), 0, 1, 0, 0}, - {&__pyx_n_s_FrozenList, __pyx_k_FrozenList, sizeof(__pyx_k_FrozenList), 0, 0, 1, 1}, - {&__pyx_kp_u_FrozenList_frozen_r, __pyx_k_FrozenList_frozen_r, sizeof(__pyx_k_FrozenList_frozen_r), 0, 1, 0, 0}, - {&__pyx_kp_s_Incompatible_checksums_s_vs_0x94, __pyx_k_Incompatible_checksums_s_vs_0x94, sizeof(__pyx_k_Incompatible_checksums_s_vs_0x94), 0, 0, 1, 0}, - {&__pyx_n_s_MutableSequence, __pyx_k_MutableSequence, sizeof(__pyx_k_MutableSequence), 0, 0, 1, 1}, - {&__pyx_n_s_PickleError, __pyx_k_PickleError, sizeof(__pyx_k_PickleError), 0, 0, 1, 1}, - {&__pyx_n_s_RuntimeError, __pyx_k_RuntimeError, sizeof(__pyx_k_RuntimeError), 0, 0, 1, 1}, - {&__pyx_n_s_aiohttp__frozenlist, __pyx_k_aiohttp__frozenlist, sizeof(__pyx_k_aiohttp__frozenlist), 0, 0, 1, 1}, - {&__pyx_n_s_clear, __pyx_k_clear, sizeof(__pyx_k_clear), 0, 0, 1, 1}, - {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, - {&__pyx_n_s_collections_abc, __pyx_k_collections_abc, sizeof(__pyx_k_collections_abc), 0, 0, 1, 1}, - {&__pyx_n_s_count, __pyx_k_count, sizeof(__pyx_k_count), 0, 0, 1, 1}, - {&__pyx_n_s_dict, __pyx_k_dict, sizeof(__pyx_k_dict), 0, 0, 1, 1}, - {&__pyx_n_s_format, __pyx_k_format, sizeof(__pyx_k_format), 0, 0, 1, 1}, - {&__pyx_n_s_getstate, __pyx_k_getstate, sizeof(__pyx_k_getstate), 0, 0, 1, 1}, - {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, - {&__pyx_n_s_index, __pyx_k_index, sizeof(__pyx_k_index), 0, 0, 1, 1}, - {&__pyx_n_s_item, __pyx_k_item, sizeof(__pyx_k_item), 0, 0, 1, 1}, - {&__pyx_n_s_items, __pyx_k_items, sizeof(__pyx_k_items), 0, 0, 1, 1}, - {&__pyx_n_s_iter, __pyx_k_iter, sizeof(__pyx_k_iter), 0, 0, 1, 1}, - {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, - {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, - {&__pyx_n_s_new, __pyx_k_new, sizeof(__pyx_k_new), 0, 0, 1, 1}, - {&__pyx_n_s_pickle, __pyx_k_pickle, sizeof(__pyx_k_pickle), 0, 0, 1, 1}, - {&__pyx_n_s_pop, __pyx_k_pop, sizeof(__pyx_k_pop), 0, 0, 1, 1}, - {&__pyx_n_s_pos, __pyx_k_pos, sizeof(__pyx_k_pos), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_PickleError, __pyx_k_pyx_PickleError, sizeof(__pyx_k_pyx_PickleError), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_checksum, __pyx_k_pyx_checksum, sizeof(__pyx_k_pyx_checksum), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_result, __pyx_k_pyx_result, sizeof(__pyx_k_pyx_result), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_state, __pyx_k_pyx_state, sizeof(__pyx_k_pyx_state), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_type, __pyx_k_pyx_type, sizeof(__pyx_k_pyx_type), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_unpickle_FrozenList, __pyx_k_pyx_unpickle_FrozenList, sizeof(__pyx_k_pyx_unpickle_FrozenList), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_vtable, __pyx_k_pyx_vtable, sizeof(__pyx_k_pyx_vtable), 0, 0, 1, 1}, - {&__pyx_n_s_reduce, __pyx_k_reduce, sizeof(__pyx_k_reduce), 0, 0, 1, 1}, - {&__pyx_n_s_reduce_cython, __pyx_k_reduce_cython, sizeof(__pyx_k_reduce_cython), 0, 0, 1, 1}, - {&__pyx_n_s_reduce_ex, __pyx_k_reduce_ex, sizeof(__pyx_k_reduce_ex), 0, 0, 1, 1}, - {&__pyx_n_s_register, __pyx_k_register, sizeof(__pyx_k_register), 0, 0, 1, 1}, - {&__pyx_n_s_remove, __pyx_k_remove, sizeof(__pyx_k_remove), 0, 0, 1, 1}, - {&__pyx_n_s_reversed, __pyx_k_reversed, sizeof(__pyx_k_reversed), 0, 0, 1, 1}, - {&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1}, - {&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1}, - {&__pyx_kp_s_stringsource, __pyx_k_stringsource, sizeof(__pyx_k_stringsource), 0, 0, 1, 0}, - {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, - {&__pyx_n_s_update, __pyx_k_update, sizeof(__pyx_k_update), 0, 0, 1, 1}, - {0, 0, 0, 0, 0, 0, 0} -}; -static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { - __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s_RuntimeError); if (!__pyx_builtin_RuntimeError) __PYX_ERR(0, 19, __pyx_L1_error) - return 0; - __pyx_L1_error:; - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); - - /* "aiohttp/_frozenlist.pyx":19 - * cdef object _check_frozen(self): - * if self.frozen: - * raise RuntimeError("Cannot modify frozen list.") # <<<<<<<<<<<<<< - * - * cdef inline object _fast_len(self): - */ - __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_u_Cannot_modify_frozen_list); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 19, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple_); - __Pyx_GIVEREF(__pyx_tuple_); - - /* "(tree fragment)":1 - * def __pyx_unpickle_FrozenList(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - __pyx_tuple__2 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__2); - __Pyx_GIVEREF(__pyx_tuple__2); - __pyx_codeobj__3 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__2, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_FrozenList, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__3)) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_RefNannyFinishContext(); - return 0; - __pyx_L1_error:; - __Pyx_RefNannyFinishContext(); - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { - if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); - __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_2 = PyInt_FromLong(2); if (unlikely(!__pyx_int_2)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_3 = PyInt_FromLong(3); if (unlikely(!__pyx_int_3)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_4 = PyInt_FromLong(4); if (unlikely(!__pyx_int_4)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_5 = PyInt_FromLong(5); if (unlikely(!__pyx_int_5)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_155820355 = PyInt_FromLong(155820355L); if (unlikely(!__pyx_int_155820355)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) __PYX_ERR(0, 1, __pyx_L1_error) - return 0; - __pyx_L1_error:; - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ - -static int __Pyx_modinit_global_init_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); - /*--- Global init code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_variable_export_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); - /*--- Variable export code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_function_export_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); - /*--- Function export code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_type_init_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); - /*--- Type init code ---*/ - __pyx_vtabptr_7aiohttp_11_frozenlist_FrozenList = &__pyx_vtable_7aiohttp_11_frozenlist_FrozenList; - __pyx_vtable_7aiohttp_11_frozenlist_FrozenList._check_frozen = (PyObject *(*)(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *))__pyx_f_7aiohttp_11_frozenlist_10FrozenList__check_frozen; - __pyx_vtable_7aiohttp_11_frozenlist_FrozenList._fast_len = (PyObject *(*)(struct __pyx_obj_7aiohttp_11_frozenlist_FrozenList *))__pyx_f_7aiohttp_11_frozenlist_10FrozenList__fast_len; - if (PyType_Ready(&__pyx_type_7aiohttp_11_frozenlist_FrozenList) < 0) __PYX_ERR(0, 4, __pyx_L1_error) - #if PY_VERSION_HEX < 0x030800B1 - __pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_print = 0; - #endif - if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_dictoffset && __pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_getattro == PyObject_GenericGetAttr)) { - __pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_getattro = __Pyx_PyObject_GenericGetAttr; - } - if (__Pyx_SetVtable(__pyx_type_7aiohttp_11_frozenlist_FrozenList.tp_dict, __pyx_vtabptr_7aiohttp_11_frozenlist_FrozenList) < 0) __PYX_ERR(0, 4, __pyx_L1_error) - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_FrozenList, (PyObject *)&__pyx_type_7aiohttp_11_frozenlist_FrozenList) < 0) __PYX_ERR(0, 4, __pyx_L1_error) - if (__Pyx_setup_reduce((PyObject*)&__pyx_type_7aiohttp_11_frozenlist_FrozenList) < 0) __PYX_ERR(0, 4, __pyx_L1_error) - __pyx_ptype_7aiohttp_11_frozenlist_FrozenList = &__pyx_type_7aiohttp_11_frozenlist_FrozenList; - __Pyx_RefNannyFinishContext(); - return 0; - __pyx_L1_error:; - __Pyx_RefNannyFinishContext(); - return -1; -} - -static int __Pyx_modinit_type_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); - /*--- Type import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_variable_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); - /*--- Variable import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_function_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); - /*--- Function import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - - -#if PY_MAJOR_VERSION < 3 -#ifdef CYTHON_NO_PYINIT_EXPORT -#define __Pyx_PyMODINIT_FUNC void -#else -#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC -#endif -#else -#ifdef CYTHON_NO_PYINIT_EXPORT -#define __Pyx_PyMODINIT_FUNC PyObject * -#else -#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC -#endif -#endif - - -#if PY_MAJOR_VERSION < 3 -__Pyx_PyMODINIT_FUNC init_frozenlist(void) CYTHON_SMALL_CODE; /*proto*/ -__Pyx_PyMODINIT_FUNC init_frozenlist(void) -#else -__Pyx_PyMODINIT_FUNC PyInit__frozenlist(void) CYTHON_SMALL_CODE; /*proto*/ -__Pyx_PyMODINIT_FUNC PyInit__frozenlist(void) -#if CYTHON_PEP489_MULTI_PHASE_INIT -{ - return PyModuleDef_Init(&__pyx_moduledef); -} -static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { - #if PY_VERSION_HEX >= 0x030700A1 - static PY_INT64_T main_interpreter_id = -1; - PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); - if (main_interpreter_id == -1) { - main_interpreter_id = current_id; - return (unlikely(current_id == -1)) ? -1 : 0; - } else if (unlikely(main_interpreter_id != current_id)) - #else - static PyInterpreterState *main_interpreter = NULL; - PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; - if (!main_interpreter) { - main_interpreter = current_interpreter; - } else if (unlikely(main_interpreter != current_interpreter)) - #endif - { - PyErr_SetString( - PyExc_ImportError, - "Interpreter change detected - this module can only be loaded into one interpreter per process."); - return -1; - } - return 0; -} -static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { - PyObject *value = PyObject_GetAttrString(spec, from_name); - int result = 0; - if (likely(value)) { - if (allow_none || value != Py_None) { - result = PyDict_SetItemString(moddict, to_name, value); - } - Py_DECREF(value); - } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - } else { - result = -1; - } - return result; -} -static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { - PyObject *module = NULL, *moddict, *modname; - if (__Pyx_check_single_interpreter()) - return NULL; - if (__pyx_m) - return __Pyx_NewRef(__pyx_m); - modname = PyObject_GetAttrString(spec, "name"); - if (unlikely(!modname)) goto bad; - module = PyModule_NewObject(modname); - Py_DECREF(modname); - if (unlikely(!module)) goto bad; - moddict = PyModule_GetDict(module); - if (unlikely(!moddict)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; - return module; -bad: - Py_XDECREF(module); - return NULL; -} - - -static CYTHON_SMALL_CODE int __pyx_pymod_exec__frozenlist(PyObject *__pyx_pyinit_module) -#endif -#endif -{ - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - __Pyx_RefNannyDeclarations - #if CYTHON_PEP489_MULTI_PHASE_INIT - if (__pyx_m) { - if (__pyx_m == __pyx_pyinit_module) return 0; - PyErr_SetString(PyExc_RuntimeError, "Module '_frozenlist' has already been imported. Re-initialisation is not supported."); - return -1; - } - #elif PY_MAJOR_VERSION >= 3 - if (__pyx_m) return __Pyx_NewRef(__pyx_m); - #endif - #if CYTHON_REFNANNY -__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); -if (!__Pyx_RefNanny) { - PyErr_Clear(); - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); - if (!__Pyx_RefNanny) - Py_FatalError("failed to import 'refnanny' module"); -} -#endif - __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit__frozenlist(void)", 0); - if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #ifdef __Pxy_PyFrame_Initialize_Offsets - __Pxy_PyFrame_Initialize_Offsets(); - #endif - __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) - #ifdef __Pyx_CyFunction_USED - if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_FusedFunction_USED - if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_Coroutine_USED - if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_Generator_USED - if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_AsyncGen_USED - if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_StopAsyncIteration_USED - if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - /*--- Library function declarations ---*/ - /*--- Threads initialization code ---*/ - #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - #ifdef WITH_THREAD /* Python build with threading support? */ - PyEval_InitThreads(); - #endif - #endif - /*--- Module creation code ---*/ - #if CYTHON_PEP489_MULTI_PHASE_INIT - __pyx_m = __pyx_pyinit_module; - Py_INCREF(__pyx_m); - #else - #if PY_MAJOR_VERSION < 3 - __pyx_m = Py_InitModule4("_frozenlist", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); - #else - __pyx_m = PyModule_Create(&__pyx_moduledef); - #endif - if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_d); - __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_b); - __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_cython_runtime); - if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); - /*--- Initialize various global constants etc. ---*/ - if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) - if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - if (__pyx_module_is_main_aiohttp___frozenlist) { - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - } - #if PY_MAJOR_VERSION >= 3 - { - PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) - if (!PyDict_GetItemString(modules, "aiohttp._frozenlist")) { - if (unlikely(PyDict_SetItemString(modules, "aiohttp._frozenlist", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) - } - } - #endif - /*--- Builtin init code ---*/ - if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error; - /*--- Constants init code ---*/ - if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error; - /*--- Global type/function init code ---*/ - (void)__Pyx_modinit_global_init_code(); - (void)__Pyx_modinit_variable_export_code(); - (void)__Pyx_modinit_function_export_code(); - if (unlikely(__Pyx_modinit_type_init_code() != 0)) goto __pyx_L1_error; - (void)__Pyx_modinit_type_import_code(); - (void)__Pyx_modinit_variable_import_code(); - (void)__Pyx_modinit_function_import_code(); - /*--- Execution code ---*/ - #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) - if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - - /* "aiohttp/_frozenlist.pyx":1 - * from collections.abc import MutableSequence # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_n_s_MutableSequence); - __Pyx_GIVEREF(__pyx_n_s_MutableSequence); - PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_MutableSequence); - __pyx_t_2 = __Pyx_Import(__pyx_n_s_collections_abc, __pyx_t_1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_MutableSequence); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_MutableSequence, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "aiohttp/_frozenlist.pyx":108 - * - * - * MutableSequence.register(FrozenList) # <<<<<<<<<<<<<< - */ - __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_MutableSequence); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 108, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_register); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 108, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_1, ((PyObject *)__pyx_ptype_7aiohttp_11_frozenlist_FrozenList)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 108, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "(tree fragment)":1 - * def __pyx_unpickle_FrozenList(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_11_frozenlist_1__pyx_unpickle_FrozenList, NULL, __pyx_n_s_aiohttp__frozenlist); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_FrozenList, __pyx_t_2) < 0) __PYX_ERR(1, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "aiohttp/_frozenlist.pyx":1 - * from collections.abc import MutableSequence # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /*--- Wrapped vars code ---*/ - - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - if (__pyx_m) { - if (__pyx_d) { - __Pyx_AddTraceback("init aiohttp._frozenlist", __pyx_clineno, __pyx_lineno, __pyx_filename); - } - Py_CLEAR(__pyx_m); - } else if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_ImportError, "init aiohttp._frozenlist"); - } - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - #if CYTHON_PEP489_MULTI_PHASE_INIT - return (__pyx_m != NULL) ? 0 : -1; - #elif PY_MAJOR_VERSION >= 3 - return __pyx_m; - #else - return; - #endif -} - -/* --- Runtime support code --- */ -/* Refnanny */ -#if CYTHON_REFNANNY -static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { - PyObject *m = NULL, *p = NULL; - void *r = NULL; - m = PyImport_ImportModule(modname); - if (!m) goto end; - p = PyObject_GetAttrString(m, "RefNannyAPI"); - if (!p) goto end; - r = PyLong_AsVoidPtr(p); -end: - Py_XDECREF(p); - Py_XDECREF(m); - return (__Pyx_RefNannyAPIStruct *)r; -} -#endif - -/* PyObjectGetAttrStr */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { - PyTypeObject* tp = Py_TYPE(obj); - if (likely(tp->tp_getattro)) - return tp->tp_getattro(obj, attr_name); -#if PY_MAJOR_VERSION < 3 - if (likely(tp->tp_getattr)) - return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); -#endif - return PyObject_GetAttr(obj, attr_name); -} -#endif - -/* GetBuiltinName */ -static PyObject *__Pyx_GetBuiltinName(PyObject *name) { - PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); - if (unlikely(!result)) { - PyErr_Format(PyExc_NameError, -#if PY_MAJOR_VERSION >= 3 - "name '%U' is not defined", name); -#else - "name '%.200s' is not defined", PyString_AS_STRING(name)); -#endif - } - return result; -} - -/* RaiseDoubleKeywords */ -static void __Pyx_RaiseDoubleKeywordsError( - const char* func_name, - PyObject* kw_name) -{ - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION >= 3 - "%s() got multiple values for keyword argument '%U'", func_name, kw_name); - #else - "%s() got multiple values for keyword argument '%s'", func_name, - PyString_AsString(kw_name)); - #endif -} - -/* ParseKeywords */ -static int __Pyx_ParseOptionalKeywords( - PyObject *kwds, - PyObject **argnames[], - PyObject *kwds2, - PyObject *values[], - Py_ssize_t num_pos_args, - const char* function_name) -{ - PyObject *key = 0, *value = 0; - Py_ssize_t pos = 0; - PyObject*** name; - PyObject*** first_kw_arg = argnames + num_pos_args; - while (PyDict_Next(kwds, &pos, &key, &value)) { - name = first_kw_arg; - while (*name && (**name != key)) name++; - if (*name) { - values[name-argnames] = value; - continue; - } - name = first_kw_arg; - #if PY_MAJOR_VERSION < 3 - if (likely(PyString_CheckExact(key)) || likely(PyString_Check(key))) { - while (*name) { - if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) - && _PyString_Eq(**name, key)) { - values[name-argnames] = value; - break; - } - name++; - } - if (*name) continue; - else { - PyObject*** argname = argnames; - while (argname != first_kw_arg) { - if ((**argname == key) || ( - (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) - && _PyString_Eq(**argname, key))) { - goto arg_passed_twice; - } - argname++; - } - } - } else - #endif - if (likely(PyUnicode_Check(key))) { - while (*name) { - int cmp = (**name == key) ? 0 : - #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 - (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 : - #endif - PyUnicode_Compare(**name, key); - if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; - if (cmp == 0) { - values[name-argnames] = value; - break; - } - name++; - } - if (*name) continue; - else { - PyObject*** argname = argnames; - while (argname != first_kw_arg) { - int cmp = (**argname == key) ? 0 : - #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 - (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 : - #endif - PyUnicode_Compare(**argname, key); - if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; - if (cmp == 0) goto arg_passed_twice; - argname++; - } - } - } else - goto invalid_keyword_type; - if (kwds2) { - if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; - } else { - goto invalid_keyword; - } - } - return 0; -arg_passed_twice: - __Pyx_RaiseDoubleKeywordsError(function_name, key); - goto bad; -invalid_keyword_type: - PyErr_Format(PyExc_TypeError, - "%.200s() keywords must be strings", function_name); - goto bad; -invalid_keyword: - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION < 3 - "%.200s() got an unexpected keyword argument '%.200s'", - function_name, PyString_AsString(key)); - #else - "%s() got an unexpected keyword argument '%U'", - function_name, key); - #endif -bad: - return -1; -} - -/* RaiseArgTupleInvalid */ -static void __Pyx_RaiseArgtupleInvalid( - const char* func_name, - int exact, - Py_ssize_t num_min, - Py_ssize_t num_max, - Py_ssize_t num_found) -{ - Py_ssize_t num_expected; - const char *more_or_less; - if (num_found < num_min) { - num_expected = num_min; - more_or_less = "at least"; - } else { - num_expected = num_max; - more_or_less = "at most"; - } - if (exact) { - more_or_less = "exactly"; - } - PyErr_Format(PyExc_TypeError, - "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", - func_name, more_or_less, num_expected, - (num_expected == 1) ? "" : "s", num_found); -} - -/* PyObjectCall */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { - PyObject *result; - ternaryfunc call = func->ob_type->tp_call; - if (unlikely(!call)) - return PyObject_Call(func, arg, kw); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = (*call)(func, arg, kw); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* PyErrFetchRestore */ -#if CYTHON_FAST_THREAD_STATE -static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { - PyObject *tmp_type, *tmp_value, *tmp_tb; - tmp_type = tstate->curexc_type; - tmp_value = tstate->curexc_value; - tmp_tb = tstate->curexc_traceback; - tstate->curexc_type = type; - tstate->curexc_value = value; - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); -} -static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { - *type = tstate->curexc_type; - *value = tstate->curexc_value; - *tb = tstate->curexc_traceback; - tstate->curexc_type = 0; - tstate->curexc_value = 0; - tstate->curexc_traceback = 0; -} -#endif - -/* RaiseException */ -#if PY_MAJOR_VERSION < 3 -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, - CYTHON_UNUSED PyObject *cause) { - __Pyx_PyThreadState_declare - Py_XINCREF(type); - if (!value || value == Py_None) - value = NULL; - else - Py_INCREF(value); - if (!tb || tb == Py_None) - tb = NULL; - else { - Py_INCREF(tb); - if (!PyTraceBack_Check(tb)) { - PyErr_SetString(PyExc_TypeError, - "raise: arg 3 must be a traceback or None"); - goto raise_error; - } - } - if (PyType_Check(type)) { -#if CYTHON_COMPILING_IN_PYPY - if (!value) { - Py_INCREF(Py_None); - value = Py_None; - } -#endif - PyErr_NormalizeException(&type, &value, &tb); - } else { - if (value) { - PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); - goto raise_error; - } - value = type; - type = (PyObject*) Py_TYPE(type); - Py_INCREF(type); - if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { - PyErr_SetString(PyExc_TypeError, - "raise: exception class must be a subclass of BaseException"); - goto raise_error; - } - } - __Pyx_PyThreadState_assign - __Pyx_ErrRestore(type, value, tb); - return; -raise_error: - Py_XDECREF(value); - Py_XDECREF(type); - Py_XDECREF(tb); - return; -} -#else -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { - PyObject* owned_instance = NULL; - if (tb == Py_None) { - tb = 0; - } else if (tb && !PyTraceBack_Check(tb)) { - PyErr_SetString(PyExc_TypeError, - "raise: arg 3 must be a traceback or None"); - goto bad; - } - if (value == Py_None) - value = 0; - if (PyExceptionInstance_Check(type)) { - if (value) { - PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); - goto bad; - } - value = type; - type = (PyObject*) Py_TYPE(value); - } else if (PyExceptionClass_Check(type)) { - PyObject *instance_class = NULL; - if (value && PyExceptionInstance_Check(value)) { - instance_class = (PyObject*) Py_TYPE(value); - if (instance_class != type) { - int is_subclass = PyObject_IsSubclass(instance_class, type); - if (!is_subclass) { - instance_class = NULL; - } else if (unlikely(is_subclass == -1)) { - goto bad; - } else { - type = instance_class; - } - } - } - if (!instance_class) { - PyObject *args; - if (!value) - args = PyTuple_New(0); - else if (PyTuple_Check(value)) { - Py_INCREF(value); - args = value; - } else - args = PyTuple_Pack(1, value); - if (!args) - goto bad; - owned_instance = PyObject_Call(type, args, NULL); - Py_DECREF(args); - if (!owned_instance) - goto bad; - value = owned_instance; - if (!PyExceptionInstance_Check(value)) { - PyErr_Format(PyExc_TypeError, - "calling %R should have returned an instance of " - "BaseException, not %R", - type, Py_TYPE(value)); - goto bad; - } - } - } else { - PyErr_SetString(PyExc_TypeError, - "raise: exception class must be a subclass of BaseException"); - goto bad; - } - if (cause) { - PyObject *fixed_cause; - if (cause == Py_None) { - fixed_cause = NULL; - } else if (PyExceptionClass_Check(cause)) { - fixed_cause = PyObject_CallObject(cause, NULL); - if (fixed_cause == NULL) - goto bad; - } else if (PyExceptionInstance_Check(cause)) { - fixed_cause = cause; - Py_INCREF(fixed_cause); - } else { - PyErr_SetString(PyExc_TypeError, - "exception causes must derive from " - "BaseException"); - goto bad; - } - PyException_SetCause(value, fixed_cause); - } - PyErr_SetObject(type, value); - if (tb) { -#if CYTHON_COMPILING_IN_PYPY - PyObject *tmp_type, *tmp_value, *tmp_tb; - PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); - Py_INCREF(tb); - PyErr_Restore(tmp_type, tmp_value, tb); - Py_XDECREF(tmp_tb); -#else - PyThreadState *tstate = __Pyx_PyThreadState_Current; - PyObject* tmp_tb = tstate->curexc_traceback; - if (tb != tmp_tb) { - Py_INCREF(tb); - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_tb); - } -#endif - } -bad: - Py_XDECREF(owned_instance); - return; -} -#endif - -/* GetItemInt */ -static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { - PyObject *r; - if (!j) return NULL; - r = PyObject_GetItem(o, j); - Py_DECREF(j); - return r; -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - Py_ssize_t wrapped_i = i; - if (wraparound & unlikely(i < 0)) { - wrapped_i += PyList_GET_SIZE(o); - } - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { - PyObject *r = PyList_GET_ITEM(o, wrapped_i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - Py_ssize_t wrapped_i = i; - if (wraparound & unlikely(i < 0)) { - wrapped_i += PyTuple_GET_SIZE(o); - } - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, wrapped_i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS - if (is_list || PyList_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); - if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { - PyObject *r = PyList_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } - else if (PyTuple_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); - if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } else { - PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; - if (likely(m && m->sq_item)) { - if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { - Py_ssize_t l = m->sq_length(o); - if (likely(l >= 0)) { - i += l; - } else { - if (!PyErr_ExceptionMatches(PyExc_OverflowError)) - return NULL; - PyErr_Clear(); - } - } - return m->sq_item(o, i); - } - } -#else - if (is_list || PySequence_Check(o)) { - return PySequence_GetItem(o, i); - } -#endif - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -} - -/* ObjectGetItem */ -#if CYTHON_USE_TYPE_SLOTS -static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) { - PyObject *runerr; - Py_ssize_t key_value; - PySequenceMethods *m = Py_TYPE(obj)->tp_as_sequence; - if (unlikely(!(m && m->sq_item))) { - PyErr_Format(PyExc_TypeError, "'%.200s' object is not subscriptable", Py_TYPE(obj)->tp_name); - return NULL; - } - key_value = __Pyx_PyIndex_AsSsize_t(index); - if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { - return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1); - } - if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { - PyErr_Clear(); - PyErr_Format(PyExc_IndexError, "cannot fit '%.200s' into an index-sized integer", Py_TYPE(index)->tp_name); - } - return NULL; -} -static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key) { - PyMappingMethods *m = Py_TYPE(obj)->tp_as_mapping; - if (likely(m && m->mp_subscript)) { - return m->mp_subscript(obj, key); - } - return __Pyx_PyObject_GetIndex(obj, key); -} -#endif - -/* PyFunctionFastCall */ -#if CYTHON_FAST_PYCALL -static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, - PyObject *globals) { - PyFrameObject *f; - PyThreadState *tstate = __Pyx_PyThreadState_Current; - PyObject **fastlocals; - Py_ssize_t i; - PyObject *result; - assert(globals != NULL); - /* XXX Perhaps we should create a specialized - PyFrame_New() that doesn't take locals, but does - take builtins without sanity checking them. - */ - assert(tstate != NULL); - f = PyFrame_New(tstate, co, globals, NULL); - if (f == NULL) { - return NULL; - } - fastlocals = __Pyx_PyFrame_GetLocalsplus(f); - for (i = 0; i < na; i++) { - Py_INCREF(*args); - fastlocals[i] = *args++; - } - result = PyEval_EvalFrameEx(f,0); - ++tstate->recursion_depth; - Py_DECREF(f); - --tstate->recursion_depth; - return result; -} -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { - PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); - PyObject *globals = PyFunction_GET_GLOBALS(func); - PyObject *argdefs = PyFunction_GET_DEFAULTS(func); - PyObject *closure; -#if PY_MAJOR_VERSION >= 3 - PyObject *kwdefs; -#endif - PyObject *kwtuple, **k; - PyObject **d; - Py_ssize_t nd; - Py_ssize_t nk; - PyObject *result; - assert(kwargs == NULL || PyDict_Check(kwargs)); - nk = kwargs ? PyDict_Size(kwargs) : 0; - if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { - return NULL; - } - if ( -#if PY_MAJOR_VERSION >= 3 - co->co_kwonlyargcount == 0 && -#endif - likely(kwargs == NULL || nk == 0) && - co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { - if (argdefs == NULL && co->co_argcount == nargs) { - result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); - goto done; - } - else if (nargs == 0 && argdefs != NULL - && co->co_argcount == Py_SIZE(argdefs)) { - /* function called with no arguments, but all parameters have - a default value: use default values as arguments .*/ - args = &PyTuple_GET_ITEM(argdefs, 0); - result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); - goto done; - } - } - if (kwargs != NULL) { - Py_ssize_t pos, i; - kwtuple = PyTuple_New(2 * nk); - if (kwtuple == NULL) { - result = NULL; - goto done; - } - k = &PyTuple_GET_ITEM(kwtuple, 0); - pos = i = 0; - while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { - Py_INCREF(k[i]); - Py_INCREF(k[i+1]); - i += 2; - } - nk = i / 2; - } - else { - kwtuple = NULL; - k = NULL; - } - closure = PyFunction_GET_CLOSURE(func); -#if PY_MAJOR_VERSION >= 3 - kwdefs = PyFunction_GET_KW_DEFAULTS(func); -#endif - if (argdefs != NULL) { - d = &PyTuple_GET_ITEM(argdefs, 0); - nd = Py_SIZE(argdefs); - } - else { - d = NULL; - nd = 0; - } -#if PY_MAJOR_VERSION >= 3 - result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, - args, (int)nargs, - k, (int)nk, - d, (int)nd, kwdefs, closure); -#else - result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, - args, (int)nargs, - k, (int)nk, - d, (int)nd, closure); -#endif - Py_XDECREF(kwtuple); -done: - Py_LeaveRecursiveCall(); - return result; -} -#endif -#endif - -/* PyObjectCallMethO */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { - PyObject *self, *result; - PyCFunction cfunc; - cfunc = PyCFunction_GET_FUNCTION(func); - self = PyCFunction_GET_SELF(func); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = cfunc(self, arg); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* PyObjectCallNoArg */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { -#if CYTHON_FAST_PYCALL - if (PyFunction_Check(func)) { - return __Pyx_PyFunction_FastCall(func, NULL, 0); - } -#endif -#ifdef __Pyx_CyFunction_USED - if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func))) -#else - if (likely(PyCFunction_Check(func))) -#endif - { - if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { - return __Pyx_PyObject_CallMethO(func, NULL); - } - } - return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); -} -#endif - -/* PyCFunctionFastCall */ -#if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { - PyCFunctionObject *func = (PyCFunctionObject*)func_obj; - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); - int flags = PyCFunction_GET_FLAGS(func); - assert(PyCFunction_Check(func)); - assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); - assert(nargs >= 0); - assert(nargs == 0 || args != NULL); - /* _PyCFunction_FastCallDict() must not be called with an exception set, - because it may clear it (directly or indirectly) and so the - caller loses its exception */ - assert(!PyErr_Occurred()); - if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { - return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); - } else { - return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); - } -} -#endif - -/* PyObjectCallOneArg */ -#if CYTHON_COMPILING_IN_CPYTHON -static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { - PyObject *result; - PyObject *args = PyTuple_New(1); - if (unlikely(!args)) return NULL; - Py_INCREF(arg); - PyTuple_SET_ITEM(args, 0, arg); - result = __Pyx_PyObject_Call(func, args, NULL); - Py_DECREF(args); - return result; -} -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { -#if CYTHON_FAST_PYCALL - if (PyFunction_Check(func)) { - return __Pyx_PyFunction_FastCall(func, &arg, 1); - } -#endif - if (likely(PyCFunction_Check(func))) { - if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { - return __Pyx_PyObject_CallMethO(func, arg); -#if CYTHON_FAST_PYCCALL - } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { - return __Pyx_PyCFunction_FastCall(func, &arg, 1); -#endif - } - } - return __Pyx__PyObject_CallOneArg(func, arg); -} -#else -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { - PyObject *result; - PyObject *args = PyTuple_Pack(1, arg); - if (unlikely(!args)) return NULL; - result = __Pyx_PyObject_Call(func, args, NULL); - Py_DECREF(args); - return result; -} -#endif - -/* PyIntCompare */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_EqObjC(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, CYTHON_UNUSED long inplace) { - if (op1 == op2) { - Py_RETURN_TRUE; - } - #if PY_MAJOR_VERSION < 3 - if (likely(PyInt_CheckExact(op1))) { - const long b = intval; - long a = PyInt_AS_LONG(op1); - if (a == b) Py_RETURN_TRUE; else Py_RETURN_FALSE; - } - #endif - #if CYTHON_USE_PYLONG_INTERNALS - if (likely(PyLong_CheckExact(op1))) { - int unequal; - unsigned long uintval; - Py_ssize_t size = Py_SIZE(op1); - const digit* digits = ((PyLongObject*)op1)->ob_digit; - if (intval == 0) { - if (size == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; - } else if (intval < 0) { - if (size >= 0) - Py_RETURN_FALSE; - intval = -intval; - size = -size; - } else { - if (size <= 0) - Py_RETURN_FALSE; - } - uintval = (unsigned long) intval; -#if PyLong_SHIFT * 4 < SIZEOF_LONG*8 - if (uintval >> (PyLong_SHIFT * 4)) { - unequal = (size != 5) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) - | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[4] != ((uintval >> (4 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); - } else -#endif -#if PyLong_SHIFT * 3 < SIZEOF_LONG*8 - if (uintval >> (PyLong_SHIFT * 3)) { - unequal = (size != 4) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) - | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); - } else -#endif -#if PyLong_SHIFT * 2 < SIZEOF_LONG*8 - if (uintval >> (PyLong_SHIFT * 2)) { - unequal = (size != 3) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) - | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); - } else -#endif -#if PyLong_SHIFT * 1 < SIZEOF_LONG*8 - if (uintval >> (PyLong_SHIFT * 1)) { - unequal = (size != 2) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) - | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)); - } else -#endif - unequal = (size != 1) || (((unsigned long) digits[0]) != (uintval & (unsigned long) PyLong_MASK)); - if (unequal == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; - } - #endif - if (PyFloat_CheckExact(op1)) { - const long b = intval; - double a = PyFloat_AS_DOUBLE(op1); - if ((double)a == (double)b) Py_RETURN_TRUE; else Py_RETURN_FALSE; - } - return ( - PyObject_RichCompare(op1, op2, Py_EQ)); -} - -/* PyObjectCall2Args */ -static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { - PyObject *args, *result = NULL; - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(function)) { - PyObject *args[2] = {arg1, arg2}; - return __Pyx_PyFunction_FastCall(function, args, 2); - } - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(function)) { - PyObject *args[2] = {arg1, arg2}; - return __Pyx_PyCFunction_FastCall(function, args, 2); - } - #endif - args = PyTuple_New(2); - if (unlikely(!args)) goto done; - Py_INCREF(arg1); - PyTuple_SET_ITEM(args, 0, arg1); - Py_INCREF(arg2); - PyTuple_SET_ITEM(args, 1, arg2); - Py_INCREF(function); - result = __Pyx_PyObject_Call(function, args, NULL); - Py_DECREF(args); - Py_DECREF(function); -done: - return result; -} - -/* PyObjectGetMethod */ -static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) { - PyObject *attr; -#if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP - PyTypeObject *tp = Py_TYPE(obj); - PyObject *descr; - descrgetfunc f = NULL; - PyObject **dictptr, *dict; - int meth_found = 0; - assert (*method == NULL); - if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) { - attr = __Pyx_PyObject_GetAttrStr(obj, name); - goto try_unpack; - } - if (unlikely(tp->tp_dict == NULL) && unlikely(PyType_Ready(tp) < 0)) { - return 0; - } - descr = _PyType_Lookup(tp, name); - if (likely(descr != NULL)) { - Py_INCREF(descr); -#if PY_MAJOR_VERSION >= 3 - #ifdef __Pyx_CyFunction_USED - if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr))) - #else - if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type))) - #endif -#else - #ifdef __Pyx_CyFunction_USED - if (likely(PyFunction_Check(descr) || __Pyx_CyFunction_Check(descr))) - #else - if (likely(PyFunction_Check(descr))) - #endif -#endif - { - meth_found = 1; - } else { - f = Py_TYPE(descr)->tp_descr_get; - if (f != NULL && PyDescr_IsData(descr)) { - attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); - Py_DECREF(descr); - goto try_unpack; - } - } - } - dictptr = _PyObject_GetDictPtr(obj); - if (dictptr != NULL && (dict = *dictptr) != NULL) { - Py_INCREF(dict); - attr = __Pyx_PyDict_GetItemStr(dict, name); - if (attr != NULL) { - Py_INCREF(attr); - Py_DECREF(dict); - Py_XDECREF(descr); - goto try_unpack; - } - Py_DECREF(dict); - } - if (meth_found) { - *method = descr; - return 1; - } - if (f != NULL) { - attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); - Py_DECREF(descr); - goto try_unpack; - } - if (descr != NULL) { - *method = descr; - return 0; - } - PyErr_Format(PyExc_AttributeError, -#if PY_MAJOR_VERSION >= 3 - "'%.50s' object has no attribute '%U'", - tp->tp_name, name); -#else - "'%.50s' object has no attribute '%.400s'", - tp->tp_name, PyString_AS_STRING(name)); -#endif - return 0; -#else - attr = __Pyx_PyObject_GetAttrStr(obj, name); - goto try_unpack; -#endif -try_unpack: -#if CYTHON_UNPACK_METHODS - if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) { - PyObject *function = PyMethod_GET_FUNCTION(attr); - Py_INCREF(function); - Py_DECREF(attr); - *method = function; - return 1; - } -#endif - *method = attr; - return 0; -} - -/* PyObjectCallMethod1 */ -static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) { - PyObject *result = __Pyx_PyObject_CallOneArg(method, arg); - Py_DECREF(method); - return result; -} -static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg) { - PyObject *method = NULL, *result; - int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); - if (likely(is_method)) { - result = __Pyx_PyObject_Call2Args(method, obj, arg); - Py_DECREF(method); - return result; - } - if (unlikely(!method)) return NULL; - return __Pyx__PyObject_CallMethod1(method, arg); -} - -/* pop_index */ -static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix) { - PyObject *r; - if (unlikely(!py_ix)) return NULL; - r = __Pyx__PyObject_PopIndex(L, py_ix); - Py_DECREF(py_ix); - return r; -} -static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix) { - return __Pyx_PyObject_CallMethod1(L, __pyx_n_s_pop, py_ix); -} -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix) { - Py_ssize_t size = PyList_GET_SIZE(L); - if (likely(size > (((PyListObject*)L)->allocated >> 1))) { - Py_ssize_t cix = ix; - if (cix < 0) { - cix += size; - } - if (likely(__Pyx_is_valid_index(cix, size))) { - PyObject* v = PyList_GET_ITEM(L, cix); - Py_SIZE(L) -= 1; - size -= 1; - memmove(&PyList_GET_ITEM(L, cix), &PyList_GET_ITEM(L, cix+1), (size_t)(size-cix)*sizeof(PyObject*)); - return v; - } - } - if (py_ix == Py_None) { - return __Pyx__PyObject_PopNewIndex(L, PyInt_FromSsize_t(ix)); - } else { - return __Pyx__PyObject_PopIndex(L, py_ix); - } -} -#endif - -/* PyErrExceptionMatches */ -#if CYTHON_FAST_THREAD_STATE -static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { - Py_ssize_t i, n; - n = PyTuple_GET_SIZE(tuple); -#if PY_MAJOR_VERSION >= 3 - for (i=0; icurexc_type; - if (exc_type == err) return 1; - if (unlikely(!exc_type)) return 0; - if (unlikely(PyTuple_Check(err))) - return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); - return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); -} -#endif - -/* GetAttr */ -static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *o, PyObject *n) { -#if CYTHON_USE_TYPE_SLOTS -#if PY_MAJOR_VERSION >= 3 - if (likely(PyUnicode_Check(n))) -#else - if (likely(PyString_Check(n))) -#endif - return __Pyx_PyObject_GetAttrStr(o, n); -#endif - return PyObject_GetAttr(o, n); -} - -/* GetAttr3 */ -static PyObject *__Pyx_GetAttr3Default(PyObject *d) { - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) - return NULL; - __Pyx_PyErr_Clear(); - Py_INCREF(d); - return d; -} -static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) { - PyObject *r = __Pyx_GetAttr(o, n); - return (likely(r)) ? r : __Pyx_GetAttr3Default(d); -} - -/* PyDictVersioning */ -#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { - PyObject **dictptr = NULL; - Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; - if (offset) { -#if CYTHON_COMPILING_IN_CPYTHON - dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); -#else - dictptr = _PyObject_GetDictPtr(obj); -#endif - } - return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; -} -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) - return 0; - return obj_dict_version == __Pyx_get_object_dict_version(obj); -} -#endif - -/* GetModuleGlobalName */ -#if CYTHON_USE_DICT_VERSIONS -static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) -#else -static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) -#endif -{ - PyObject *result; -#if !CYTHON_AVOID_BORROWED_REFS -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 - result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } else if (unlikely(PyErr_Occurred())) { - return NULL; - } -#else - result = PyDict_GetItem(__pyx_d, name); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } -#endif -#else - result = PyObject_GetItem(__pyx_d, name); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } - PyErr_Clear(); -#endif - return __Pyx_GetBuiltinName(name); -} - -/* Import */ -static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { - PyObject *empty_list = 0; - PyObject *module = 0; - PyObject *global_dict = 0; - PyObject *empty_dict = 0; - PyObject *list; - #if PY_MAJOR_VERSION < 3 - PyObject *py_import; - py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); - if (!py_import) - goto bad; - #endif - if (from_list) - list = from_list; - else { - empty_list = PyList_New(0); - if (!empty_list) - goto bad; - list = empty_list; - } - global_dict = PyModule_GetDict(__pyx_m); - if (!global_dict) - goto bad; - empty_dict = PyDict_New(); - if (!empty_dict) - goto bad; - { - #if PY_MAJOR_VERSION >= 3 - if (level == -1) { - if (strchr(__Pyx_MODULE_NAME, '.')) { - module = PyImport_ImportModuleLevelObject( - name, global_dict, empty_dict, list, 1); - if (!module) { - if (!PyErr_ExceptionMatches(PyExc_ImportError)) - goto bad; - PyErr_Clear(); - } - } - level = 0; - } - #endif - if (!module) { - #if PY_MAJOR_VERSION < 3 - PyObject *py_level = PyInt_FromLong(level); - if (!py_level) - goto bad; - module = PyObject_CallFunctionObjArgs(py_import, - name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); - Py_DECREF(py_level); - #else - module = PyImport_ImportModuleLevelObject( - name, global_dict, empty_dict, list, level); - #endif - } - } -bad: - #if PY_MAJOR_VERSION < 3 - Py_XDECREF(py_import); - #endif - Py_XDECREF(empty_list); - Py_XDECREF(empty_dict); - return module; -} - -/* ImportFrom */ -static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) { - PyObject* value = __Pyx_PyObject_GetAttrStr(module, name); - if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Format(PyExc_ImportError, - #if PY_MAJOR_VERSION < 3 - "cannot import name %.230s", PyString_AS_STRING(name)); - #else - "cannot import name %S", name); - #endif - } - return value; -} - -/* HasAttr */ -static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) { - PyObject *r; - if (unlikely(!__Pyx_PyBaseString_Check(n))) { - PyErr_SetString(PyExc_TypeError, - "hasattr(): attribute name must be string"); - return -1; - } - r = __Pyx_GetAttr(o, n); - if (unlikely(!r)) { - PyErr_Clear(); - return 0; - } else { - Py_DECREF(r); - return 1; - } -} - -/* PyObject_GenericGetAttrNoDict */ -#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject *attr_name) { - PyErr_Format(PyExc_AttributeError, -#if PY_MAJOR_VERSION >= 3 - "'%.50s' object has no attribute '%U'", - tp->tp_name, attr_name); -#else - "'%.50s' object has no attribute '%.400s'", - tp->tp_name, PyString_AS_STRING(attr_name)); -#endif - return NULL; -} -static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name) { - PyObject *descr; - PyTypeObject *tp = Py_TYPE(obj); - if (unlikely(!PyString_Check(attr_name))) { - return PyObject_GenericGetAttr(obj, attr_name); - } - assert(!tp->tp_dictoffset); - descr = _PyType_Lookup(tp, attr_name); - if (unlikely(!descr)) { - return __Pyx_RaiseGenericGetAttributeError(tp, attr_name); - } - Py_INCREF(descr); - #if PY_MAJOR_VERSION < 3 - if (likely(PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS))) - #endif - { - descrgetfunc f = Py_TYPE(descr)->tp_descr_get; - if (unlikely(f)) { - PyObject *res = f(descr, obj, (PyObject *)tp); - Py_DECREF(descr); - return res; - } - } - return descr; -} -#endif - -/* PyObject_GenericGetAttr */ -#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name) { - if (unlikely(Py_TYPE(obj)->tp_dictoffset)) { - return PyObject_GenericGetAttr(obj, attr_name); - } - return __Pyx_PyObject_GenericGetAttrNoDict(obj, attr_name); -} -#endif - -/* SetVTable */ -static int __Pyx_SetVtable(PyObject *dict, void *vtable) { -#if PY_VERSION_HEX >= 0x02070000 - PyObject *ob = PyCapsule_New(vtable, 0, 0); -#else - PyObject *ob = PyCObject_FromVoidPtr(vtable, 0); -#endif - if (!ob) - goto bad; - if (PyDict_SetItem(dict, __pyx_n_s_pyx_vtable, ob) < 0) - goto bad; - Py_DECREF(ob); - return 0; -bad: - Py_XDECREF(ob); - return -1; -} - -/* SetupReduce */ -static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { - int ret; - PyObject *name_attr; - name_attr = __Pyx_PyObject_GetAttrStr(meth, __pyx_n_s_name); - if (likely(name_attr)) { - ret = PyObject_RichCompareBool(name_attr, name, Py_EQ); - } else { - ret = -1; - } - if (unlikely(ret < 0)) { - PyErr_Clear(); - ret = 0; - } - Py_XDECREF(name_attr); - return ret; -} -static int __Pyx_setup_reduce(PyObject* type_obj) { - int ret = 0; - PyObject *object_reduce = NULL; - PyObject *object_reduce_ex = NULL; - PyObject *reduce = NULL; - PyObject *reduce_ex = NULL; - PyObject *reduce_cython = NULL; - PyObject *setstate = NULL; - PyObject *setstate_cython = NULL; -#if CYTHON_USE_PYTYPE_LOOKUP - if (_PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate)) goto GOOD; -#else - if (PyObject_HasAttr(type_obj, __pyx_n_s_getstate)) goto GOOD; -#endif -#if CYTHON_USE_PYTYPE_LOOKUP - object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto BAD; -#else - object_reduce_ex = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto BAD; -#endif - reduce_ex = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce_ex); if (unlikely(!reduce_ex)) goto BAD; - if (reduce_ex == object_reduce_ex) { -#if CYTHON_USE_PYTYPE_LOOKUP - object_reduce = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto BAD; -#else - object_reduce = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto BAD; -#endif - reduce = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce); if (unlikely(!reduce)) goto BAD; - if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, __pyx_n_s_reduce_cython)) { - reduce_cython = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce_cython); if (unlikely(!reduce_cython)) goto BAD; - ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce, reduce_cython); if (unlikely(ret < 0)) goto BAD; - ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce_cython); if (unlikely(ret < 0)) goto BAD; - setstate = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate); - if (!setstate) PyErr_Clear(); - if (!setstate || __Pyx_setup_reduce_is_named(setstate, __pyx_n_s_setstate_cython)) { - setstate_cython = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate_cython); if (unlikely(!setstate_cython)) goto BAD; - ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate, setstate_cython); if (unlikely(ret < 0)) goto BAD; - ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate_cython); if (unlikely(ret < 0)) goto BAD; - } - PyType_Modified((PyTypeObject*)type_obj); - } - } - goto GOOD; -BAD: - if (!PyErr_Occurred()) - PyErr_Format(PyExc_RuntimeError, "Unable to initialize pickling for %s", ((PyTypeObject*)type_obj)->tp_name); - ret = -1; -GOOD: -#if !CYTHON_USE_PYTYPE_LOOKUP - Py_XDECREF(object_reduce); - Py_XDECREF(object_reduce_ex); -#endif - Py_XDECREF(reduce); - Py_XDECREF(reduce_ex); - Py_XDECREF(reduce_cython); - Py_XDECREF(setstate); - Py_XDECREF(setstate_cython); - return ret; -} - -/* CLineInTraceback */ -#ifndef CYTHON_CLINE_IN_TRACEBACK -static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { - PyObject *use_cline; - PyObject *ptype, *pvalue, *ptraceback; -#if CYTHON_COMPILING_IN_CPYTHON - PyObject **cython_runtime_dict; -#endif - if (unlikely(!__pyx_cython_runtime)) { - return c_line; - } - __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); -#if CYTHON_COMPILING_IN_CPYTHON - cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); - if (likely(cython_runtime_dict)) { - __PYX_PY_DICT_LOOKUP_IF_MODIFIED( - use_cline, *cython_runtime_dict, - __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) - } else -#endif - { - PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); - if (use_cline_obj) { - use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; - Py_DECREF(use_cline_obj); - } else { - PyErr_Clear(); - use_cline = NULL; - } - } - if (!use_cline) { - c_line = 0; - PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); - } - else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { - c_line = 0; - } - __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); - return c_line; -} -#endif - -/* CodeObjectCache */ -static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { - int start = 0, mid = 0, end = count - 1; - if (end >= 0 && code_line > entries[end].code_line) { - return count; - } - while (start < end) { - mid = start + (end - start) / 2; - if (code_line < entries[mid].code_line) { - end = mid; - } else if (code_line > entries[mid].code_line) { - start = mid + 1; - } else { - return mid; - } - } - if (code_line <= entries[mid].code_line) { - return mid; - } else { - return mid + 1; - } -} -static PyCodeObject *__pyx_find_code_object(int code_line) { - PyCodeObject* code_object; - int pos; - if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { - return NULL; - } - pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); - if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { - return NULL; - } - code_object = __pyx_code_cache.entries[pos].code_object; - Py_INCREF(code_object); - return code_object; -} -static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { - int pos, i; - __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; - if (unlikely(!code_line)) { - return; - } - if (unlikely(!entries)) { - entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); - if (likely(entries)) { - __pyx_code_cache.entries = entries; - __pyx_code_cache.max_count = 64; - __pyx_code_cache.count = 1; - entries[0].code_line = code_line; - entries[0].code_object = code_object; - Py_INCREF(code_object); - } - return; - } - pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); - if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { - PyCodeObject* tmp = entries[pos].code_object; - entries[pos].code_object = code_object; - Py_DECREF(tmp); - return; - } - if (__pyx_code_cache.count == __pyx_code_cache.max_count) { - int new_max = __pyx_code_cache.max_count + 64; - entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( - __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry)); - if (unlikely(!entries)) { - return; - } - __pyx_code_cache.entries = entries; - __pyx_code_cache.max_count = new_max; - } - for (i=__pyx_code_cache.count; i>pos; i--) { - entries[i] = entries[i-1]; - } - entries[pos].code_line = code_line; - entries[pos].code_object = code_object; - __pyx_code_cache.count++; - Py_INCREF(code_object); -} - -/* AddTraceback */ -#include "compile.h" -#include "frameobject.h" -#include "traceback.h" -static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( - const char *funcname, int c_line, - int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; - #if PY_MAJOR_VERSION < 3 - py_srcfile = PyString_FromString(filename); - #else - py_srcfile = PyUnicode_FromString(filename); - #endif - if (!py_srcfile) goto bad; - if (c_line) { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); - #else - py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); - #endif - } - else { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromString(funcname); - #else - py_funcname = PyUnicode_FromString(funcname); - #endif - } - if (!py_funcname) goto bad; - py_code = __Pyx_PyCode_New( - 0, - 0, - 0, - 0, - 0, - __pyx_empty_bytes, /*PyObject *code,*/ - __pyx_empty_tuple, /*PyObject *consts,*/ - __pyx_empty_tuple, /*PyObject *names,*/ - __pyx_empty_tuple, /*PyObject *varnames,*/ - __pyx_empty_tuple, /*PyObject *freevars,*/ - __pyx_empty_tuple, /*PyObject *cellvars,*/ - py_srcfile, /*PyObject *filename,*/ - py_funcname, /*PyObject *name,*/ - py_line, - __pyx_empty_bytes /*PyObject *lnotab*/ - ); - Py_DECREF(py_srcfile); - Py_DECREF(py_funcname); - return py_code; -bad: - Py_XDECREF(py_srcfile); - Py_XDECREF(py_funcname); - return NULL; -} -static void __Pyx_AddTraceback(const char *funcname, int c_line, - int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyFrameObject *py_frame = 0; - PyThreadState *tstate = __Pyx_PyThreadState_Current; - if (c_line) { - c_line = __Pyx_CLineForTraceback(tstate, c_line); - } - py_code = __pyx_find_code_object(c_line ? -c_line : py_line); - if (!py_code) { - py_code = __Pyx_CreateCodeObjectForTraceback( - funcname, c_line, py_line, filename); - if (!py_code) goto bad; - __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); - } - py_frame = PyFrame_New( - tstate, /*PyThreadState *tstate,*/ - py_code, /*PyCodeObject *code,*/ - __pyx_d, /*PyObject *globals,*/ - 0 /*PyObject *locals*/ - ); - if (!py_frame) goto bad; - __Pyx_PyFrame_SetLineNumber(py_frame, py_line); - PyTraceBack_Here(py_frame); -bad: - Py_XDECREF(py_code); - Py_XDECREF(py_frame); -} - -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(int) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(int) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(int) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(int), - little, !is_unsigned); - } -} - -/* CIntFromPyVerify */ -#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ - __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) -#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ - __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) -#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ - {\ - func_type value = func_value;\ - if (sizeof(target_type) < sizeof(func_type)) {\ - if (unlikely(value != (func_type) (target_type) value)) {\ - func_type zero = 0;\ - if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ - return (target_type) -1;\ - if (is_unsigned && unlikely(value < zero))\ - goto raise_neg_overflow;\ - else\ - goto raise_overflow;\ - }\ - }\ - return (target_type) value;\ - } - -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(long) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(long) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(long) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(long), - little, !is_unsigned); - } -} - -/* CIntFromPy */ -static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; - const int is_unsigned = neg_one > const_zero; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x))) { - if (sizeof(long) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) - } else { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - goto raise_neg_overflow; - } - return (long) val; - } - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (long) 0; - case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) - case 2: - if (8 * sizeof(long) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { - return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - case 3: - if (8 * sizeof(long) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { - return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - case 4: - if (8 * sizeof(long) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { - return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - } -#endif -#if CYTHON_COMPILING_IN_CPYTHON - if (unlikely(Py_SIZE(x) < 0)) { - goto raise_neg_overflow; - } -#else - { - int result = PyObject_RichCompareBool(x, Py_False, Py_LT); - if (unlikely(result < 0)) - return (long) -1; - if (unlikely(result == 1)) - goto raise_neg_overflow; - } -#endif - if (sizeof(long) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif - } - } else { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (long) 0; - case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) - case -2: - if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 2: - if (8 * sizeof(long) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case -3: - if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 3: - if (8 * sizeof(long) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case -4: - if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 4: - if (8 * sizeof(long) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - } -#endif - if (sizeof(long) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif - } - } - { -#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) - PyErr_SetString(PyExc_RuntimeError, - "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); -#else - long val; - PyObject *v = __Pyx_PyNumber_IntOrLong(x); - #if PY_MAJOR_VERSION < 3 - if (likely(v) && !PyLong_Check(v)) { - PyObject *tmp = v; - v = PyNumber_Long(tmp); - Py_DECREF(tmp); - } - #endif - if (likely(v)) { - int one = 1; int is_little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&val; - int ret = _PyLong_AsByteArray((PyLongObject *)v, - bytes, sizeof(val), - is_little, !is_unsigned); - Py_DECREF(v); - if (likely(!ret)) - return val; - } -#endif - return (long) -1; - } - } else { - long val; - PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (long) -1; - val = __Pyx_PyInt_As_long(tmp); - Py_DECREF(tmp); - return val; - } -raise_overflow: - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to long"); - return (long) -1; -raise_neg_overflow: - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to long"); - return (long) -1; -} - -/* CIntFromPy */ -static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; - const int is_unsigned = neg_one > const_zero; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x))) { - if (sizeof(int) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) - } else { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - goto raise_neg_overflow; - } - return (int) val; - } - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (int) 0; - case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) - case 2: - if (8 * sizeof(int) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { - return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - case 3: - if (8 * sizeof(int) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { - return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - case 4: - if (8 * sizeof(int) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { - return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - } -#endif -#if CYTHON_COMPILING_IN_CPYTHON - if (unlikely(Py_SIZE(x) < 0)) { - goto raise_neg_overflow; - } -#else - { - int result = PyObject_RichCompareBool(x, Py_False, Py_LT); - if (unlikely(result < 0)) - return (int) -1; - if (unlikely(result == 1)) - goto raise_neg_overflow; - } -#endif - if (sizeof(int) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif - } - } else { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (int) 0; - case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) - case -2: - if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 2: - if (8 * sizeof(int) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case -3: - if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 3: - if (8 * sizeof(int) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case -4: - if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 4: - if (8 * sizeof(int) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { - return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - } -#endif - if (sizeof(int) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif - } - } - { -#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) - PyErr_SetString(PyExc_RuntimeError, - "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); -#else - int val; - PyObject *v = __Pyx_PyNumber_IntOrLong(x); - #if PY_MAJOR_VERSION < 3 - if (likely(v) && !PyLong_Check(v)) { - PyObject *tmp = v; - v = PyNumber_Long(tmp); - Py_DECREF(tmp); - } - #endif - if (likely(v)) { - int one = 1; int is_little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&val; - int ret = _PyLong_AsByteArray((PyLongObject *)v, - bytes, sizeof(val), - is_little, !is_unsigned); - Py_DECREF(v); - if (likely(!ret)) - return val; - } -#endif - return (int) -1; - } - } else { - int val; - PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (int) -1; - val = __Pyx_PyInt_As_int(tmp); - Py_DECREF(tmp); - return val; - } -raise_overflow: - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to int"); - return (int) -1; -raise_neg_overflow: - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to int"); - return (int) -1; -} - -/* FastTypeChecks */ -#if CYTHON_COMPILING_IN_CPYTHON -static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { - while (a) { - a = a->tp_base; - if (a == b) - return 1; - } - return b == &PyBaseObject_Type; -} -static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { - PyObject *mro; - if (a == b) return 1; - mro = a->tp_mro; - if (likely(mro)) { - Py_ssize_t i, n; - n = PyTuple_GET_SIZE(mro); - for (i = 0; i < n; i++) { - if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) - return 1; - } - return 0; - } - return __Pyx_InBases(a, b); -} -#if PY_MAJOR_VERSION == 2 -static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { - PyObject *exception, *value, *tb; - int res; - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ErrFetch(&exception, &value, &tb); - res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; - if (unlikely(res == -1)) { - PyErr_WriteUnraisable(err); - res = 0; - } - if (!res) { - res = PyObject_IsSubclass(err, exc_type2); - if (unlikely(res == -1)) { - PyErr_WriteUnraisable(err); - res = 0; - } - } - __Pyx_ErrRestore(exception, value, tb); - return res; -} -#else -static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { - int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; - if (!res) { - res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); - } - return res; -} -#endif -static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { - Py_ssize_t i, n; - assert(PyExceptionClass_Check(exc_type)); - n = PyTuple_GET_SIZE(tuple); -#if PY_MAJOR_VERSION >= 3 - for (i=0; ip) { - #if PY_MAJOR_VERSION < 3 - if (t->is_unicode) { - *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); - } else if (t->intern) { - *t->p = PyString_InternFromString(t->s); - } else { - *t->p = PyString_FromStringAndSize(t->s, t->n - 1); - } - #else - if (t->is_unicode | t->is_str) { - if (t->intern) { - *t->p = PyUnicode_InternFromString(t->s); - } else if (t->encoding) { - *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); - } else { - *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); - } - } else { - *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); - } - #endif - if (!*t->p) - return -1; - if (PyObject_Hash(*t->p) == -1) - return -1; - ++t; - } - return 0; -} - -static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { - return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); -} -static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { - Py_ssize_t ignore; - return __Pyx_PyObject_AsStringAndSize(o, &ignore); -} -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT -#if !CYTHON_PEP393_ENABLED -static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { - char* defenc_c; - PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); - if (!defenc) return NULL; - defenc_c = PyBytes_AS_STRING(defenc); -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - { - char* end = defenc_c + PyBytes_GET_SIZE(defenc); - char* c; - for (c = defenc_c; c < end; c++) { - if ((unsigned char) (*c) >= 128) { - PyUnicode_AsASCIIString(o); - return NULL; - } - } - } -#endif - *length = PyBytes_GET_SIZE(defenc); - return defenc_c; -} -#else -static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { - if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - if (likely(PyUnicode_IS_ASCII(o))) { - *length = PyUnicode_GET_LENGTH(o); - return PyUnicode_AsUTF8(o); - } else { - PyUnicode_AsASCIIString(o); - return NULL; - } -#else - return PyUnicode_AsUTF8AndSize(o, length); -#endif -} -#endif -#endif -static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT - if ( -#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - __Pyx_sys_getdefaultencoding_not_ascii && -#endif - PyUnicode_Check(o)) { - return __Pyx_PyUnicode_AsStringAndSize(o, length); - } else -#endif -#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) - if (PyByteArray_Check(o)) { - *length = PyByteArray_GET_SIZE(o); - return PyByteArray_AS_STRING(o); - } else -#endif - { - char* result; - int r = PyBytes_AsStringAndSize(o, &result, length); - if (unlikely(r < 0)) { - return NULL; - } else { - return result; - } - } -} -static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { - int is_true = x == Py_True; - if (is_true | (x == Py_False) | (x == Py_None)) return is_true; - else return PyObject_IsTrue(x); -} -static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { - int retval; - if (unlikely(!x)) return -1; - retval = __Pyx_PyObject_IsTrue(x); - Py_DECREF(x); - return retval; -} -static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { -#if PY_MAJOR_VERSION >= 3 - if (PyLong_Check(result)) { - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "__int__ returned non-int (type %.200s). " - "The ability to return an instance of a strict subclass of int " - "is deprecated, and may be removed in a future version of Python.", - Py_TYPE(result)->tp_name)) { - Py_DECREF(result); - return NULL; - } - return result; - } -#endif - PyErr_Format(PyExc_TypeError, - "__%.4s__ returned non-%.4s (type %.200s)", - type_name, type_name, Py_TYPE(result)->tp_name); - Py_DECREF(result); - return NULL; -} -static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { -#if CYTHON_USE_TYPE_SLOTS - PyNumberMethods *m; -#endif - const char *name = NULL; - PyObject *res = NULL; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x) || PyLong_Check(x))) -#else - if (likely(PyLong_Check(x))) -#endif - return __Pyx_NewRef(x); -#if CYTHON_USE_TYPE_SLOTS - m = Py_TYPE(x)->tp_as_number; - #if PY_MAJOR_VERSION < 3 - if (m && m->nb_int) { - name = "int"; - res = m->nb_int(x); - } - else if (m && m->nb_long) { - name = "long"; - res = m->nb_long(x); - } - #else - if (likely(m && m->nb_int)) { - name = "int"; - res = m->nb_int(x); - } - #endif -#else - if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { - res = PyNumber_Int(x); - } -#endif - if (likely(res)) { -#if PY_MAJOR_VERSION < 3 - if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { -#else - if (unlikely(!PyLong_CheckExact(res))) { -#endif - return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); - } - } - else if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "an integer is required"); - } - return res; -} -static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { - Py_ssize_t ival; - PyObject *x; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_CheckExact(b))) { - if (sizeof(Py_ssize_t) >= sizeof(long)) - return PyInt_AS_LONG(b); - else - return PyInt_AsSsize_t(b); - } -#endif - if (likely(PyLong_CheckExact(b))) { - #if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)b)->ob_digit; - const Py_ssize_t size = Py_SIZE(b); - if (likely(__Pyx_sst_abs(size) <= 1)) { - ival = likely(size) ? digits[0] : 0; - if (size == -1) ival = -ival; - return ival; - } else { - switch (size) { - case 2: - if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { - return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -2: - if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case 3: - if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { - return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -3: - if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case 4: - if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { - return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -4: - if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - } - } - #endif - return PyLong_AsSsize_t(b); - } - x = PyNumber_Index(b); - if (!x) return -1; - ival = PyInt_AsSsize_t(x); - Py_DECREF(x); - return ival; -} -static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { - return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); -} -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { - return PyInt_FromSize_t(ival); -} - - -#endif /* Py_PYTHON_H */ diff --git a/venv/Lib/site-packages/aiohttp/_websocket.c b/venv/Lib/site-packages/aiohttp/_websocket.c index 8082bfef..03cc4326 100644 --- a/venv/Lib/site-packages/aiohttp/_websocket.c +++ b/venv/Lib/site-packages/aiohttp/_websocket.c @@ -1,15 +1,22 @@ -/* Generated by Cython 0.29.13 */ +/* Generated by Cython 0.24.1 */ + +/* BEGIN: Cython Metadata +{ + "distutils": { + "depends": [] + }, + "module_name": "aiohttp._websocket" +} +END: Cython Metadata */ #define PY_SSIZE_T_CLEAN #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. -#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) - #error Cython requires Python 2.6+ or Python 3.3+. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03020000) + #error Cython requires Python 2.6+ or Python 3.2+. #else -#define CYTHON_ABI "0_29_13" -#define CYTHON_HEX_VERSION 0x001D0DF0 -#define CYTHON_FUTURE_DIVISION 1 +#define CYTHON_ABI "0_24_1" #include #ifndef offsetof #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) @@ -31,12 +38,6 @@ #ifndef DL_EXPORT #define DL_EXPORT(t) t #endif -#define __PYX_COMMA , -#ifndef HAVE_LONG_LONG - #if PY_VERSION_HEX >= 0x02070000 - #define HAVE_LONG_LONG - #endif -#endif #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif @@ -45,259 +46,20 @@ #endif #ifdef PYPY_VERSION #define CYTHON_COMPILING_IN_PYPY 1 - #define CYTHON_COMPILING_IN_PYSTON 0 - #define CYTHON_COMPILING_IN_CPYTHON 0 - #undef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 0 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #if PY_VERSION_HEX < 0x03050000 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #elif !defined(CYTHON_USE_ASYNC_SLOTS) - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #undef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 0 - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #undef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 1 - #undef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 0 - #undef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 0 - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #undef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 0 - #undef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 0 - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 -#elif defined(PYSTON_VERSION) - #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 1 #define CYTHON_COMPILING_IN_CPYTHON 0 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #undef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 0 - #undef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 0 - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 #else #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 0 #define CYTHON_COMPILING_IN_CPYTHON 1 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) - #define CYTHON_USE_PYTYPE_LOOKUP 1 - #endif - #if PY_MAJOR_VERSION < 3 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #elif !defined(CYTHON_USE_ASYNC_SLOTS) - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #elif !defined(CYTHON_USE_PYLONG_INTERNALS) - #define CYTHON_USE_PYLONG_INTERNALS 1 - #endif - #ifndef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 1 - #endif - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #if PY_VERSION_HEX < 0x030300F0 - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #elif !defined(CYTHON_USE_UNICODE_WRITER) - #define CYTHON_USE_UNICODE_WRITER 1 - #endif - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #ifndef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 1 - #endif - #ifndef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 1 - #endif - #ifndef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) - #endif - #ifndef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) - #endif - #ifndef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) - #endif - #ifndef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) - #endif #endif -#if !defined(CYTHON_FAST_PYCCALL) -#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#if !defined(CYTHON_USE_PYLONG_INTERNALS) && CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x02070000 + #define CYTHON_USE_PYLONG_INTERNALS 1 #endif #if CYTHON_USE_PYLONG_INTERNALS #include "longintrepr.h" #undef SHIFT #undef BASE #undef MASK - #ifdef SIZEOF_VOID_P - enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; - #endif -#endif -#ifndef __has_attribute - #define __has_attribute(x) 0 -#endif -#ifndef __has_cpp_attribute - #define __has_cpp_attribute(x) 0 -#endif -#ifndef CYTHON_RESTRICT - #if defined(__GNUC__) - #define CYTHON_RESTRICT __restrict__ - #elif defined(_MSC_VER) && _MSC_VER >= 1400 - #define CYTHON_RESTRICT __restrict - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_RESTRICT restrict - #else - #define CYTHON_RESTRICT - #endif -#endif -#ifndef CYTHON_UNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -#endif -#ifndef CYTHON_MAYBE_UNUSED_VAR -# if defined(__cplusplus) - template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } -# else -# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) -# endif -#endif -#ifndef CYTHON_NCP_UNUSED -# if CYTHON_COMPILING_IN_CPYTHON -# define CYTHON_NCP_UNUSED -# else -# define CYTHON_NCP_UNUSED CYTHON_UNUSED -# endif -#endif -#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) -#ifdef _MSC_VER - #ifndef _MSC_STDINT_H_ - #if _MSC_VER < 1300 - typedef unsigned char uint8_t; - typedef unsigned int uint32_t; - #else - typedef unsigned __int8 uint8_t; - typedef unsigned __int32 uint32_t; - #endif - #endif -#else - #include -#endif -#ifndef CYTHON_FALLTHROUGH - #if defined(__cplusplus) && __cplusplus >= 201103L - #if __has_cpp_attribute(fallthrough) - #define CYTHON_FALLTHROUGH [[fallthrough]] - #elif __has_cpp_attribute(clang::fallthrough) - #define CYTHON_FALLTHROUGH [[clang::fallthrough]] - #elif __has_cpp_attribute(gnu::fallthrough) - #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] - #endif - #endif - #ifndef CYTHON_FALLTHROUGH - #if __has_attribute(fallthrough) - #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) - #else - #define CYTHON_FALLTHROUGH - #endif - #endif - #if defined(__clang__ ) && defined(__apple_build_version__) - #if __apple_build_version__ < 7000000 - #undef CYTHON_FALLTHROUGH - #define CYTHON_FALLTHROUGH - #endif - #endif -#endif - -#ifndef CYTHON_INLINE - #if defined(__clang__) - #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) - #elif defined(__GNUC__) - #define CYTHON_INLINE __inline__ - #elif defined(_MSC_VER) - #define CYTHON_INLINE __inline - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_INLINE inline - #else - #define CYTHON_INLINE - #endif #endif - #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) #define Py_OptimizeFlag 0 #endif @@ -310,13 +72,8 @@ #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" -#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) -#else #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) -#endif #define __Pyx_DefaultClassType PyType_Type #endif #ifndef Py_TPFLAGS_CHECKTYPES @@ -331,124 +88,24 @@ #ifndef Py_TPFLAGS_HAVE_FINALIZE #define Py_TPFLAGS_HAVE_FINALIZE 0 #endif -#ifndef METH_STACKLESS - #define METH_STACKLESS 0 -#endif -#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) - #ifndef METH_FASTCALL - #define METH_FASTCALL 0x80 - #endif - typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); - typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, - Py_ssize_t nargs, PyObject *kwnames); -#else - #define __Pyx_PyCFunctionFast _PyCFunctionFast - #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords -#endif -#if CYTHON_FAST_PYCCALL -#define __Pyx_PyFastCFunction_Check(func)\ - ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) -#else -#define __Pyx_PyFastCFunction_Check(func) 0 -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) - #define PyObject_Malloc(s) PyMem_Malloc(s) - #define PyObject_Free(p) PyMem_Free(p) - #define PyObject_Realloc(p) PyMem_Realloc(p) -#endif -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 - #define PyMem_RawMalloc(n) PyMem_Malloc(n) - #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) - #define PyMem_RawFree(p) PyMem_Free(p) -#endif -#if CYTHON_COMPILING_IN_PYSTON - #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) - #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) -#else - #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) - #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) -#endif -#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 - #define __Pyx_PyThreadState_Current PyThreadState_GET() -#elif PY_VERSION_HEX >= 0x03060000 - #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() -#elif PY_VERSION_HEX >= 0x03000000 - #define __Pyx_PyThreadState_Current PyThreadState_GET() -#else - #define __Pyx_PyThreadState_Current _PyThreadState_Current -#endif -#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) -#include "pythread.h" -#define Py_tss_NEEDS_INIT 0 -typedef int Py_tss_t; -static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { - *key = PyThread_create_key(); - return 0; -} -static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { - Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); - *key = Py_tss_NEEDS_INIT; - return key; -} -static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { - PyObject_Free(key); -} -static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { - return *key != Py_tss_NEEDS_INIT; -} -static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { - PyThread_delete_key(*key); - *key = Py_tss_NEEDS_INIT; -} -static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { - return PyThread_set_key_value(*key, value); -} -static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { - return PyThread_get_key_value(*key); -} -#endif -#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) -#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) -#else -#define __Pyx_PyDict_NewPresized(n) PyDict_New() -#endif -#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION - #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) -#else - #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) -#endif -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS -#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) -#else -#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) -#endif #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) #define CYTHON_PEP393_ENABLED 1 #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ 0 : _PyUnicode_Ready((PyObject *)(op))) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) - #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) - #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) #else #define CYTHON_PEP393_ENABLED 0 - #define PyUnicode_1BYTE_KIND 1 - #define PyUnicode_2BYTE_KIND 2 - #define PyUnicode_4BYTE_KIND 4 #define __Pyx_PyUnicode_READY(op) (0) #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) - #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) - #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) #endif #if CYTHON_COMPILING_IN_PYPY @@ -468,8 +125,13 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) #endif -#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) -#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) #else @@ -484,7 +146,6 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #define PyString_Type PyUnicode_Type #define PyString_Check PyUnicode_Check #define PyString_CheckExact PyUnicode_CheckExact - #define PyObject_Unicode PyObject_Str #endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) @@ -496,11 +157,7 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #ifndef PySet_CheckExact #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) #endif -#if CYTHON_ASSUME_SAFE_MACROS - #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) -#else - #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) -#endif +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) #if PY_MAJOR_VERSION >= 3 #define PyIntObject PyLongObject #define PyInt_Type PyLong_Type @@ -535,26 +192,46 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t #endif #if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func)) #else #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) #endif -#if CYTHON_USE_ASYNC_SLOTS - #if PY_VERSION_HEX >= 0x030500B1 - #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods - #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) +#if PY_VERSION_HEX >= 0x030500B1 +#define __Pyx_PyAsyncMethodsStruct PyAsyncMethods +#define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) +#elif CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 +typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; +} __Pyx_PyAsyncMethodsStruct; +#define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) +#else +#define __Pyx_PyType_AsAsync(obj) NULL +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict #else - #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #define CYTHON_RESTRICT #endif -#else - #define __Pyx_PyType_AsAsync(obj) NULL #endif -#ifndef __Pyx_PyAsyncMethodsStruct - typedef struct { - unaryfunc am_await; - unaryfunc am_aiter; - unaryfunc am_anext; - } __Pyx_PyAsyncMethodsStruct; +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) + +#ifndef CYTHON_INLINE + #if defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_INLINE inline + #else + #define CYTHON_INLINE + #endif #endif #if defined(WIN32) || defined(MS_WINDOWS) @@ -582,6 +259,14 @@ static CYTHON_INLINE float __PYX_NAN() { __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \ } +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif + #ifndef __PYX_EXTERN_C #ifdef __cplusplus #define __PYX_EXTERN_C extern "C" @@ -592,25 +277,43 @@ static CYTHON_INLINE float __PYX_NAN() { #define __PYX_HAVE__aiohttp___websocket #define __PYX_HAVE_API__aiohttp___websocket -/* Early includes */ -#include -#include +#include "string.h" +#include "stdio.h" #include "pythread.h" -#include +#include "stdint.h" #ifdef _OPENMP #include #endif /* _OPENMP */ -#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#ifdef PYREX_WITHOUT_ASSERTIONS #define CYTHON_WITHOUT_ASSERTIONS #endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; #define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 -#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 -#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0 #define __PYX_DEFAULT_STRING_ENCODING "" #define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString #define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize @@ -626,9 +329,6 @@ typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* enc (sizeof(type) == sizeof(Py_ssize_t) &&\ (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ v == (type)PY_SSIZE_T_MAX))) ) -static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { - return (size_t) i < (size_t) limit; -} #if defined (__cplusplus) && __cplusplus >= 201103L #include #define __Pyx_sst_abs(value) std::abs(value) @@ -636,8 +336,8 @@ static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { #define __Pyx_sst_abs(value) abs(value) #elif SIZEOF_LONG >= SIZEOF_SIZE_T #define __Pyx_sst_abs(value) labs(value) -#elif defined (_MSC_VER) - #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (_MSC_VER) && defined (_M_X64) + #define __Pyx_sst_abs(value) _abs64(value) #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define __Pyx_sst_abs(value) llabs(value) #elif defined (__GNUC__) @@ -645,8 +345,8 @@ static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { #else #define __Pyx_sst_abs(value) ((value<0) ? -value : value) #endif -static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); -static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); #define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) #define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) #define __Pyx_PyBytes_FromString PyBytes_FromString @@ -659,41 +359,34 @@ static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize #endif -#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) #define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) #define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) #define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) #define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) #define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) -static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { +#if PY_MAJOR_VERSION < 3 +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) +{ const Py_UNICODE *u_end = u; while (*u_end++) ; return (size_t)(u_end - u - 1); } +#else +#define __Pyx_Py_UNICODE_strlen Py_UNICODE_strlen +#endif #define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) #define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode #define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode #define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) #define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) -static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +#define __Pyx_PyBool_FromLong(b) ((b) ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False)) static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); -static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); -#define __Pyx_PySequence_Tuple(obj)\ - (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); -#if CYTHON_ASSUME_SAFE_MACROS +#if CYTHON_COMPILING_IN_CPYTHON #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) #else #define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) @@ -768,7 +461,7 @@ static int __Pyx_init_sys_getdefaultencoding_params(void) { if (!default_encoding) goto bad; default_encoding_c = PyBytes_AsString(default_encoding); if (!default_encoding_c) goto bad; - __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c)); if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); Py_DECREF(default_encoding); @@ -789,12 +482,10 @@ bad: #define likely(x) (x) #define unlikely(x) (x) #endif /* __GNUC__ */ -static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } -static PyObject *__pyx_m = NULL; +static PyObject *__pyx_m; static PyObject *__pyx_d; static PyObject *__pyx_b; -static PyObject *__pyx_cython_runtime = NULL; static PyObject *__pyx_empty_tuple; static PyObject *__pyx_empty_bytes; static PyObject *__pyx_empty_unicode; @@ -805,7 +496,7 @@ static const char *__pyx_filename; static const char *__pyx_f[] = { - "aiohttp\\_websocket.pyx", + "aiohttp/_websocket.pyx", "type.pxd", "bool.pxd", "complex.pxd", @@ -878,8 +569,17 @@ static const char *__pyx_f[] = { #define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) /* PyObjectGetAttrStr.proto */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} #else #define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) #endif @@ -899,130 +599,9 @@ static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ const char* function_name); -/* PyCFunctionFastCall.proto */ -#if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); -#else -#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) -#endif - -/* PyFunctionFastCall.proto */ -#if CYTHON_FAST_PYCALL -#define __Pyx_PyFunction_FastCall(func, args, nargs)\ - __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); -#else -#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) -#endif -#define __Pyx_BUILD_ASSERT_EXPR(cond)\ - (sizeof(char [1 - 2*!(cond)]) - 1) -#ifndef Py_MEMBER_SIZE -#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) -#endif - static size_t __pyx_pyframe_localsplus_offset = 0; - #include "frameobject.h" - #define __Pxy_PyFrame_Initialize_Offsets()\ - ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ - (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) - #define __Pyx_PyFrame_GetLocalsplus(frame)\ - (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) -#endif - -/* PyObjectCall.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); -#else -#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) -#endif - -/* PyObjectCallMethO.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); -#endif - -/* PyObjectCallOneArg.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); - -/* TypeImport.proto */ -#ifndef __PYX_HAVE_RT_ImportType_proto -#define __PYX_HAVE_RT_ImportType_proto -enum __Pyx_ImportType_CheckSize { - __Pyx_ImportType_CheckSize_Error = 0, - __Pyx_ImportType_CheckSize_Warn = 1, - __Pyx_ImportType_CheckSize_Ignore = 2 -}; -static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); -#endif - -/* PyDictVersioning.proto */ -#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) -#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) -#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ - (version_var) = __PYX_GET_DICT_VERSION(dict);\ - (cache_var) = (value); -#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ - static PY_UINT64_T __pyx_dict_version = 0;\ - static PyObject *__pyx_dict_cached_value = NULL;\ - if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ - (VAR) = __pyx_dict_cached_value;\ - } else {\ - (VAR) = __pyx_dict_cached_value = (LOOKUP);\ - __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ - }\ -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); -#else -#define __PYX_GET_DICT_VERSION(dict) (0) -#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) -#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); -#endif - -/* PyThreadStateGet.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; -#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; -#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type -#else -#define __Pyx_PyThreadState_declare -#define __Pyx_PyThreadState_assign -#define __Pyx_PyErr_Occurred() PyErr_Occurred() -#endif - -/* PyErrFetchRestore.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) -#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) -#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) -#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) -#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) -static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); -static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) -#else -#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) -#endif -#else -#define __Pyx_PyErr_Clear() PyErr_Clear() -#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) -#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) -#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) -#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) -#endif - -/* CLineInTraceback.proto */ -#ifdef CYTHON_CLINE_IN_TRACEBACK -#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) -#else -static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); -#endif +/* ArgTypeTest.proto */ +static CYTHON_INLINE int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, + const char *name, int exact); /* CodeObjectCache.proto */ typedef struct { @@ -1052,21 +631,23 @@ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); /* CIntFromPy.proto */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); -/* FastTypeChecks.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) -static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); -static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); -static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(void); + +/* PyIdentifierFromString.proto */ +#if !defined(__Pyx_PyIdentifier_FromString) +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s) #else -#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) -#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) -#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) + #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s) +#endif #endif -#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) -/* CheckBinaryVersion.proto */ -static int __Pyx_check_binary_version(void); +/* ModuleImport.proto */ +static PyObject *__Pyx_ImportModule(const char *name); + +/* TypeImport.proto */ +static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, size_t size, int strict); /* InitStrings.proto */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); @@ -1159,7 +740,6 @@ static PyTypeObject *__pyx_ptype_7cpython_7complex_complex = 0; /* Module declarations from 'aiohttp._websocket' */ #define __Pyx_MODULE_NAME "aiohttp._websocket" -extern int __pyx_module_is_main_aiohttp___websocket; int __pyx_module_is_main_aiohttp___websocket = 0; /* Implementation of 'aiohttp._websocket' */ @@ -1168,7 +748,6 @@ static const char __pyx_k_i[] = "i"; static const char __pyx_k_data[] = "data"; static const char __pyx_k_main[] = "__main__"; static const char __pyx_k_mask[] = "mask"; -static const char __pyx_k_name[] = "__name__"; static const char __pyx_k_test[] = "__test__"; static const char __pyx_k_range[] = "range"; static const char __pyx_k_in_buf[] = "in_buf"; @@ -1177,20 +756,17 @@ static const char __pyx_k_mask_buf[] = "mask_buf"; static const char __pyx_k_uint32_msk[] = "uint32_msk"; static const char __pyx_k_uint64_msk[] = "uint64_msk"; static const char __pyx_k_aiohttp__websocket[] = "aiohttp._websocket"; -static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; static const char __pyx_k_websocket_mask_cython[] = "_websocket_mask_cython"; -static const char __pyx_k_aiohttp__websocket_pyx[] = "aiohttp\\_websocket.pyx"; +static const char __pyx_k_home_travis_build_KeepSafe_aioh[] = "/home/travis/build/KeepSafe/aiohttp/aiohttp/_websocket.pyx"; static PyObject *__pyx_n_s_aiohttp__websocket; -static PyObject *__pyx_kp_s_aiohttp__websocket_pyx; -static PyObject *__pyx_n_s_cline_in_traceback; static PyObject *__pyx_n_s_data; static PyObject *__pyx_n_s_data_len; +static PyObject *__pyx_kp_s_home_travis_build_KeepSafe_aioh; static PyObject *__pyx_n_s_i; static PyObject *__pyx_n_s_in_buf; static PyObject *__pyx_n_s_main; static PyObject *__pyx_n_s_mask; static PyObject *__pyx_n_s_mask_buf; -static PyObject *__pyx_n_s_name; static PyObject *__pyx_n_s_range; static PyObject *__pyx_n_s_test; static PyObject *__pyx_n_s_uint32_msk; @@ -1199,20 +775,19 @@ static PyObject *__pyx_n_s_websocket_mask_cython; static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_mask, PyObject *__pyx_v_data); /* proto */ static PyObject *__pyx_tuple_; static PyObject *__pyx_codeobj__2; -/* Late includes */ /* "aiohttp/_websocket.pyx":9 * from libc.stdint cimport uint32_t, uint64_t, uintmax_t * - * def _websocket_mask_cython(object mask, object data): # <<<<<<<<<<<<<< - * """Note, this function mutates its `data` argument + * def _websocket_mask_cython(bytes mask, bytearray data): # <<<<<<<<<<<<<< + * """Note, this function mutates it's `data` argument * """ */ /* Python wrapper */ static PyObject *__pyx_pw_7aiohttp_10_websocket_1_websocket_mask_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static char __pyx_doc_7aiohttp_10_websocket__websocket_mask_cython[] = "Note, this function mutates its `data` argument\n "; -static PyMethodDef __pyx_mdef_7aiohttp_10_websocket_1_websocket_mask_cython = {"_websocket_mask_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_10_websocket_1_websocket_mask_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7aiohttp_10_websocket__websocket_mask_cython}; +static char __pyx_doc_7aiohttp_10_websocket__websocket_mask_cython[] = "Note, this function mutates it's `data` argument\n "; +static PyMethodDef __pyx_mdef_7aiohttp_10_websocket_1_websocket_mask_cython = {"_websocket_mask_cython", (PyCFunction)__pyx_pw_7aiohttp_10_websocket_1_websocket_mask_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7aiohttp_10_websocket__websocket_mask_cython}; static PyObject *__pyx_pw_7aiohttp_10_websocket_1_websocket_mask_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { PyObject *__pyx_v_mask = 0; PyObject *__pyx_v_data = 0; @@ -1227,20 +802,17 @@ static PyObject *__pyx_pw_7aiohttp_10_websocket_1_websocket_mask_cython(PyObject const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); switch (pos_args) { case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } kw_args = PyDict_Size(__pyx_kwds); switch (pos_args) { case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mask)) != 0)) kw_args--; + if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_mask)) != 0)) kw_args--; else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data)) != 0)) kw_args--; + if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_data)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("_websocket_mask_cython", 1, 2, 2, 1); __PYX_ERR(0, 9, __pyx_L3_error) } @@ -1254,8 +826,8 @@ static PyObject *__pyx_pw_7aiohttp_10_websocket_1_websocket_mask_cython(PyObject values[0] = PyTuple_GET_ITEM(__pyx_args, 0); values[1] = PyTuple_GET_ITEM(__pyx_args, 1); } - __pyx_v_mask = values[0]; - __pyx_v_data = values[1]; + __pyx_v_mask = ((PyObject*)values[0]); + __pyx_v_data = ((PyObject*)values[1]); } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; @@ -1265,9 +837,15 @@ static PyObject *__pyx_pw_7aiohttp_10_websocket_1_websocket_mask_cython(PyObject __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_mask), (&PyBytes_Type), 1, "mask", 1))) __PYX_ERR(0, 9, __pyx_L1_error) + if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_data), (&PyByteArray_Type), 1, "data", 1))) __PYX_ERR(0, 9, __pyx_L1_error) __pyx_r = __pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(__pyx_self, __pyx_v_mask, __pyx_v_data); /* function exit code */ + goto __pyx_L0; + __pyx_L1_error:; + __pyx_r = NULL; + __pyx_L0:; __Pyx_RefNannyFinishContext(); return __pyx_r; } @@ -1282,30 +860,29 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations Py_ssize_t __pyx_t_1; - int __pyx_t_2; + char *__pyx_t_2; int __pyx_t_3; - PyObject *__pyx_t_4 = NULL; - char *__pyx_t_5; - uint64_t *__pyx_t_6; - long __pyx_t_7; - uint32_t *__pyx_t_8; - Py_ssize_t __pyx_t_9; - Py_ssize_t __pyx_t_10; - Py_ssize_t __pyx_t_11; + uint64_t *__pyx_t_4; + long __pyx_t_5; + uint32_t *__pyx_t_6; + Py_ssize_t __pyx_t_7; + Py_ssize_t __pyx_t_8; __Pyx_RefNannySetupContext("_websocket_mask_cython", 0); - __Pyx_INCREF(__pyx_v_mask); - __Pyx_INCREF(__pyx_v_data); /* "aiohttp/_websocket.pyx":20 * uint64_t uint64_msk * * assert len(mask) == 4 # <<<<<<<<<<<<<< * - * if not isinstance(mask, bytes): + * data_len = len(data) */ #ifndef CYTHON_WITHOUT_ASSERTIONS if (unlikely(!Py_OptimizeFlag)) { - __pyx_t_1 = PyObject_Length(__pyx_v_mask); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 20, __pyx_L1_error) + if (unlikely(__pyx_v_mask == Py_None)) { + PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); + __PYX_ERR(0, 20, __pyx_L1_error) + } + __pyx_t_1 = PyBytes_GET_SIZE(__pyx_v_mask); if (unlikely(__pyx_t_1 == -1)) __PYX_ERR(0, 20, __pyx_L1_error) if (unlikely(!((__pyx_t_1 == 4) != 0))) { PyErr_SetNone(PyExc_AssertionError); __PYX_ERR(0, 20, __pyx_L1_error) @@ -1316,115 +893,34 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN /* "aiohttp/_websocket.pyx":22 * assert len(mask) == 4 * - * if not isinstance(mask, bytes): # <<<<<<<<<<<<<< - * mask = bytes(mask) - * - */ - __pyx_t_2 = PyBytes_Check(__pyx_v_mask); - __pyx_t_3 = ((!(__pyx_t_2 != 0)) != 0); - if (__pyx_t_3) { - - /* "aiohttp/_websocket.pyx":23 - * - * if not isinstance(mask, bytes): - * mask = bytes(mask) # <<<<<<<<<<<<<< - * - * if isinstance(data, bytearray): - */ - __pyx_t_4 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyBytes_Type)), __pyx_v_mask); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 23, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF_SET(__pyx_v_mask, __pyx_t_4); - __pyx_t_4 = 0; - - /* "aiohttp/_websocket.pyx":22 - * assert len(mask) == 4 - * - * if not isinstance(mask, bytes): # <<<<<<<<<<<<<< - * mask = bytes(mask) - * - */ - } - - /* "aiohttp/_websocket.pyx":25 - * mask = bytes(mask) - * - * if isinstance(data, bytearray): # <<<<<<<<<<<<<< - * data = data - * else: - */ - __pyx_t_3 = PyByteArray_Check(__pyx_v_data); - __pyx_t_2 = (__pyx_t_3 != 0); - if (__pyx_t_2) { - - /* "aiohttp/_websocket.pyx":26 - * - * if isinstance(data, bytearray): - * data = data # <<<<<<<<<<<<<< - * else: - * data = bytearray(data) - */ - __pyx_t_4 = __pyx_v_data; - __Pyx_INCREF(__pyx_t_4); - __Pyx_DECREF_SET(__pyx_v_data, __pyx_t_4); - __pyx_t_4 = 0; - - /* "aiohttp/_websocket.pyx":25 - * mask = bytes(mask) - * - * if isinstance(data, bytearray): # <<<<<<<<<<<<<< - * data = data - * else: - */ - goto __pyx_L4; - } - - /* "aiohttp/_websocket.pyx":28 - * data = data - * else: - * data = bytearray(data) # <<<<<<<<<<<<<< - * - * data_len = len(data) - */ - /*else*/ { - __pyx_t_4 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyByteArray_Type)), __pyx_v_data); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 28, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF_SET(__pyx_v_data, __pyx_t_4); - __pyx_t_4 = 0; - } - __pyx_L4:; - - /* "aiohttp/_websocket.pyx":30 - * data = bytearray(data) - * * data_len = len(data) # <<<<<<<<<<<<<< * in_buf = PyByteArray_AsString(data) * mask_buf = PyBytes_AsString(mask) */ - __pyx_t_1 = PyObject_Length(__pyx_v_data); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 30, __pyx_L1_error) + __pyx_t_1 = PyObject_Length(__pyx_v_data); if (unlikely(__pyx_t_1 == -1)) __PYX_ERR(0, 22, __pyx_L1_error) __pyx_v_data_len = __pyx_t_1; - /* "aiohttp/_websocket.pyx":31 + /* "aiohttp/_websocket.pyx":23 * * data_len = len(data) * in_buf = PyByteArray_AsString(data) # <<<<<<<<<<<<<< * mask_buf = PyBytes_AsString(mask) * uint32_msk = (mask_buf)[0] */ - if (!(likely(PyByteArray_CheckExact(__pyx_v_data))||((__pyx_v_data) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytearray", Py_TYPE(__pyx_v_data)->tp_name), 0))) __PYX_ERR(0, 31, __pyx_L1_error) - __pyx_t_5 = PyByteArray_AsString(((PyObject*)__pyx_v_data)); if (unlikely(__pyx_t_5 == ((char *)NULL))) __PYX_ERR(0, 31, __pyx_L1_error) - __pyx_v_in_buf = ((unsigned char *)__pyx_t_5); + __pyx_t_2 = PyByteArray_AsString(__pyx_v_data); if (unlikely(__pyx_t_2 == NULL)) __PYX_ERR(0, 23, __pyx_L1_error) + __pyx_v_in_buf = ((unsigned char *)__pyx_t_2); - /* "aiohttp/_websocket.pyx":32 + /* "aiohttp/_websocket.pyx":24 * data_len = len(data) * in_buf = PyByteArray_AsString(data) * mask_buf = PyBytes_AsString(mask) # <<<<<<<<<<<<<< * uint32_msk = (mask_buf)[0] * */ - __pyx_t_5 = PyBytes_AsString(__pyx_v_mask); if (unlikely(__pyx_t_5 == ((char *)NULL))) __PYX_ERR(0, 32, __pyx_L1_error) - __pyx_v_mask_buf = ((unsigned char const *)__pyx_t_5); + __pyx_t_2 = PyBytes_AsString(__pyx_v_mask); if (unlikely(__pyx_t_2 == NULL)) __PYX_ERR(0, 24, __pyx_L1_error) + __pyx_v_mask_buf = ((unsigned char const *)__pyx_t_2); - /* "aiohttp/_websocket.pyx":33 + /* "aiohttp/_websocket.pyx":25 * in_buf = PyByteArray_AsString(data) * mask_buf = PyBytes_AsString(mask) * uint32_msk = (mask_buf)[0] # <<<<<<<<<<<<<< @@ -1433,17 +929,17 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN */ __pyx_v_uint32_msk = (((uint32_t *)__pyx_v_mask_buf)[0]); - /* "aiohttp/_websocket.pyx":38 + /* "aiohttp/_websocket.pyx":30 * # does it need in python ?! malloc() always aligns to sizeof(long) bytes * * if sizeof(size_t) >= 8: # <<<<<<<<<<<<<< * uint64_msk = uint32_msk * uint64_msk = (uint64_msk << 32) | uint32_msk */ - __pyx_t_2 = (((sizeof(size_t)) >= 8) != 0); - if (__pyx_t_2) { + __pyx_t_3 = (((sizeof(size_t)) >= 8) != 0); + if (__pyx_t_3) { - /* "aiohttp/_websocket.pyx":39 + /* "aiohttp/_websocket.pyx":31 * * if sizeof(size_t) >= 8: * uint64_msk = uint32_msk # <<<<<<<<<<<<<< @@ -1452,7 +948,7 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN */ __pyx_v_uint64_msk = __pyx_v_uint32_msk; - /* "aiohttp/_websocket.pyx":40 + /* "aiohttp/_websocket.pyx":32 * if sizeof(size_t) >= 8: * uint64_msk = uint32_msk * uint64_msk = (uint64_msk << 32) | uint32_msk # <<<<<<<<<<<<<< @@ -1461,7 +957,7 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN */ __pyx_v_uint64_msk = ((__pyx_v_uint64_msk << 32) | __pyx_v_uint32_msk); - /* "aiohttp/_websocket.pyx":42 + /* "aiohttp/_websocket.pyx":34 * uint64_msk = (uint64_msk << 32) | uint32_msk * * while data_len >= 8: # <<<<<<<<<<<<<< @@ -1469,21 +965,21 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN * in_buf += 8 */ while (1) { - __pyx_t_2 = ((__pyx_v_data_len >= 8) != 0); - if (!__pyx_t_2) break; + __pyx_t_3 = ((__pyx_v_data_len >= 8) != 0); + if (!__pyx_t_3) break; - /* "aiohttp/_websocket.pyx":43 + /* "aiohttp/_websocket.pyx":35 * * while data_len >= 8: * (in_buf)[0] ^= uint64_msk # <<<<<<<<<<<<<< * in_buf += 8 * data_len -= 8 */ - __pyx_t_6 = ((uint64_t *)__pyx_v_in_buf); - __pyx_t_7 = 0; - (__pyx_t_6[__pyx_t_7]) = ((__pyx_t_6[__pyx_t_7]) ^ __pyx_v_uint64_msk); + __pyx_t_4 = ((uint64_t *)__pyx_v_in_buf); + __pyx_t_5 = 0; + (__pyx_t_4[__pyx_t_5]) = ((__pyx_t_4[__pyx_t_5]) ^ __pyx_v_uint64_msk); - /* "aiohttp/_websocket.pyx":44 + /* "aiohttp/_websocket.pyx":36 * while data_len >= 8: * (in_buf)[0] ^= uint64_msk * in_buf += 8 # <<<<<<<<<<<<<< @@ -1492,7 +988,7 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN */ __pyx_v_in_buf = (__pyx_v_in_buf + 8); - /* "aiohttp/_websocket.pyx":45 + /* "aiohttp/_websocket.pyx":37 * (in_buf)[0] ^= uint64_msk * in_buf += 8 * data_len -= 8 # <<<<<<<<<<<<<< @@ -1502,7 +998,7 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN __pyx_v_data_len = (__pyx_v_data_len - 8); } - /* "aiohttp/_websocket.pyx":38 + /* "aiohttp/_websocket.pyx":30 * # does it need in python ?! malloc() always aligns to sizeof(long) bytes * * if sizeof(size_t) >= 8: # <<<<<<<<<<<<<< @@ -1511,7 +1007,7 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN */ } - /* "aiohttp/_websocket.pyx":48 + /* "aiohttp/_websocket.pyx":40 * * * while data_len >= 4: # <<<<<<<<<<<<<< @@ -1519,21 +1015,21 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN * in_buf += 4 */ while (1) { - __pyx_t_2 = ((__pyx_v_data_len >= 4) != 0); - if (!__pyx_t_2) break; + __pyx_t_3 = ((__pyx_v_data_len >= 4) != 0); + if (!__pyx_t_3) break; - /* "aiohttp/_websocket.pyx":49 + /* "aiohttp/_websocket.pyx":41 * * while data_len >= 4: * (in_buf)[0] ^= uint32_msk # <<<<<<<<<<<<<< * in_buf += 4 * data_len -= 4 */ - __pyx_t_8 = ((uint32_t *)__pyx_v_in_buf); - __pyx_t_7 = 0; - (__pyx_t_8[__pyx_t_7]) = ((__pyx_t_8[__pyx_t_7]) ^ __pyx_v_uint32_msk); + __pyx_t_6 = ((uint32_t *)__pyx_v_in_buf); + __pyx_t_5 = 0; + (__pyx_t_6[__pyx_t_5]) = ((__pyx_t_6[__pyx_t_5]) ^ __pyx_v_uint32_msk); - /* "aiohttp/_websocket.pyx":50 + /* "aiohttp/_websocket.pyx":42 * while data_len >= 4: * (in_buf)[0] ^= uint32_msk * in_buf += 4 # <<<<<<<<<<<<<< @@ -1542,7 +1038,7 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN */ __pyx_v_in_buf = (__pyx_v_in_buf + 4); - /* "aiohttp/_websocket.pyx":51 + /* "aiohttp/_websocket.pyx":43 * (in_buf)[0] ^= uint32_msk * in_buf += 4 * data_len -= 4 # <<<<<<<<<<<<<< @@ -1552,44 +1048,51 @@ static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UN __pyx_v_data_len = (__pyx_v_data_len - 4); } - /* "aiohttp/_websocket.pyx":53 + /* "aiohttp/_websocket.pyx":45 * data_len -= 4 * * for i in range(0, data_len): # <<<<<<<<<<<<<< * in_buf[i] ^= mask_buf[i] + * */ __pyx_t_1 = __pyx_v_data_len; - __pyx_t_9 = __pyx_t_1; - for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) { - __pyx_v_i = __pyx_t_10; + for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_1; __pyx_t_7+=1) { + __pyx_v_i = __pyx_t_7; - /* "aiohttp/_websocket.pyx":54 + /* "aiohttp/_websocket.pyx":46 * * for i in range(0, data_len): * in_buf[i] ^= mask_buf[i] # <<<<<<<<<<<<<< + * + * return data */ - __pyx_t_11 = __pyx_v_i; - (__pyx_v_in_buf[__pyx_t_11]) = ((__pyx_v_in_buf[__pyx_t_11]) ^ (__pyx_v_mask_buf[__pyx_v_i])); + __pyx_t_8 = __pyx_v_i; + (__pyx_v_in_buf[__pyx_t_8]) = ((__pyx_v_in_buf[__pyx_t_8]) ^ (__pyx_v_mask_buf[__pyx_v_i])); } + /* "aiohttp/_websocket.pyx":48 + * in_buf[i] ^= mask_buf[i] + * + * return data # <<<<<<<<<<<<<< + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_data); + __pyx_r = __pyx_v_data; + goto __pyx_L0; + /* "aiohttp/_websocket.pyx":9 * from libc.stdint cimport uint32_t, uint64_t, uintmax_t * - * def _websocket_mask_cython(object mask, object data): # <<<<<<<<<<<<<< - * """Note, this function mutates its `data` argument + * def _websocket_mask_cython(bytes mask, bytearray data): # <<<<<<<<<<<<<< + * """Note, this function mutates it's `data` argument * """ */ /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_4); __Pyx_AddTraceback("aiohttp._websocket._websocket_mask_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; - __Pyx_XDECREF(__pyx_v_mask); - __Pyx_XDECREF(__pyx_v_data); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; @@ -1600,58 +1103,33 @@ static PyMethodDef __pyx_methods[] = { }; #if PY_MAJOR_VERSION >= 3 -#if CYTHON_PEP489_MULTI_PHASE_INIT -static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ -static int __pyx_pymod_exec__websocket(PyObject* module); /*proto*/ -static PyModuleDef_Slot __pyx_moduledef_slots[] = { - {Py_mod_create, (void*)__pyx_pymod_create}, - {Py_mod_exec, (void*)__pyx_pymod_exec__websocket}, - {0, NULL} -}; -#endif - static struct PyModuleDef __pyx_moduledef = { + #if PY_VERSION_HEX < 0x03020000 + { PyObject_HEAD_INIT(NULL) NULL, 0, NULL }, + #else PyModuleDef_HEAD_INIT, + #endif "_websocket", 0, /* m_doc */ - #if CYTHON_PEP489_MULTI_PHASE_INIT - 0, /* m_size */ - #else -1, /* m_size */ - #endif __pyx_methods /* m_methods */, - #if CYTHON_PEP489_MULTI_PHASE_INIT - __pyx_moduledef_slots, /* m_slots */ - #else NULL, /* m_reload */ - #endif NULL, /* m_traverse */ NULL, /* m_clear */ NULL /* m_free */ }; #endif -#ifndef CYTHON_SMALL_CODE -#if defined(__clang__) - #define CYTHON_SMALL_CODE -#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) - #define CYTHON_SMALL_CODE __attribute__((cold)) -#else - #define CYTHON_SMALL_CODE -#endif -#endif static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_aiohttp__websocket, __pyx_k_aiohttp__websocket, sizeof(__pyx_k_aiohttp__websocket), 0, 0, 1, 1}, - {&__pyx_kp_s_aiohttp__websocket_pyx, __pyx_k_aiohttp__websocket_pyx, sizeof(__pyx_k_aiohttp__websocket_pyx), 0, 0, 1, 0}, - {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, {&__pyx_n_s_data, __pyx_k_data, sizeof(__pyx_k_data), 0, 0, 1, 1}, {&__pyx_n_s_data_len, __pyx_k_data_len, sizeof(__pyx_k_data_len), 0, 0, 1, 1}, + {&__pyx_kp_s_home_travis_build_KeepSafe_aioh, __pyx_k_home_travis_build_KeepSafe_aioh, sizeof(__pyx_k_home_travis_build_KeepSafe_aioh), 0, 0, 1, 0}, {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1}, {&__pyx_n_s_in_buf, __pyx_k_in_buf, sizeof(__pyx_k_in_buf), 0, 0, 1, 1}, {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, {&__pyx_n_s_mask, __pyx_k_mask, sizeof(__pyx_k_mask), 0, 0, 1, 1}, {&__pyx_n_s_mask_buf, __pyx_k_mask_buf, sizeof(__pyx_k_mask_buf), 0, 0, 1, 1}, - {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, {&__pyx_n_s_uint32_msk, __pyx_k_uint32_msk, sizeof(__pyx_k_uint32_msk), 0, 0, 1, 1}, @@ -1659,28 +1137,28 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = { {&__pyx_n_s_websocket_mask_cython, __pyx_k_websocket_mask_cython, sizeof(__pyx_k_websocket_mask_cython), 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0} }; -static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { - __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 53, __pyx_L1_error) +static int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 45, __pyx_L1_error) return 0; __pyx_L1_error:; return -1; } -static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { +static int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); /* "aiohttp/_websocket.pyx":9 * from libc.stdint cimport uint32_t, uint64_t, uintmax_t * - * def _websocket_mask_cython(object mask, object data): # <<<<<<<<<<<<<< - * """Note, this function mutates its `data` argument + * def _websocket_mask_cython(bytes mask, bytearray data): # <<<<<<<<<<<<<< + * """Note, this function mutates it's `data` argument * """ */ __pyx_tuple_ = PyTuple_Pack(8, __pyx_n_s_mask, __pyx_n_s_data, __pyx_n_s_data_len, __pyx_n_s_i, __pyx_n_s_in_buf, __pyx_n_s_mask_buf, __pyx_n_s_uint32_msk, __pyx_n_s_uint64_msk); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 9, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_); - __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(2, 0, 8, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_aiohttp__websocket_pyx, __pyx_n_s_websocket_mask_cython, 9, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 9, __pyx_L1_error) + __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(2, 0, 8, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_travis_build_KeepSafe_aioh, __pyx_n_s_websocket_mask_cython, 9, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 9, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; @@ -1688,220 +1166,34 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { return -1; } -static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { +static int __Pyx_InitGlobals(void) { if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); return 0; __pyx_L1_error:; return -1; } -static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ - -static int __Pyx_modinit_global_init_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); - /*--- Global init code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_variable_export_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); - /*--- Variable export code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_function_export_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); - /*--- Function export code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_type_init_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); - /*--- Type init code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_type_import_code(void) { - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); - /*--- Type import code ---*/ - __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 9, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", - #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 - sizeof(PyTypeObject), - #else - sizeof(PyHeapTypeObject), - #endif - __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(1, 9, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 8, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_ptype_7cpython_4bool_bool = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "bool", sizeof(PyBoolObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_7cpython_4bool_bool) __PYX_ERR(2, 8, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_ptype_7cpython_7complex_complex = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "complex", sizeof(PyComplexObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_7cpython_7complex_complex) __PYX_ERR(3, 15, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_RefNannyFinishContext(); - return 0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_RefNannyFinishContext(); - return -1; -} - -static int __Pyx_modinit_variable_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); - /*--- Variable import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_function_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); - /*--- Function import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - - -#if PY_MAJOR_VERSION < 3 -#ifdef CYTHON_NO_PYINIT_EXPORT -#define __Pyx_PyMODINIT_FUNC void -#else -#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC -#endif -#else -#ifdef CYTHON_NO_PYINIT_EXPORT -#define __Pyx_PyMODINIT_FUNC PyObject * -#else -#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC -#endif -#endif - - #if PY_MAJOR_VERSION < 3 -__Pyx_PyMODINIT_FUNC init_websocket(void) CYTHON_SMALL_CODE; /*proto*/ -__Pyx_PyMODINIT_FUNC init_websocket(void) +PyMODINIT_FUNC init_websocket(void); /*proto*/ +PyMODINIT_FUNC init_websocket(void) #else -__Pyx_PyMODINIT_FUNC PyInit__websocket(void) CYTHON_SMALL_CODE; /*proto*/ -__Pyx_PyMODINIT_FUNC PyInit__websocket(void) -#if CYTHON_PEP489_MULTI_PHASE_INIT -{ - return PyModuleDef_Init(&__pyx_moduledef); -} -static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { - #if PY_VERSION_HEX >= 0x030700A1 - static PY_INT64_T main_interpreter_id = -1; - PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); - if (main_interpreter_id == -1) { - main_interpreter_id = current_id; - return (unlikely(current_id == -1)) ? -1 : 0; - } else if (unlikely(main_interpreter_id != current_id)) - #else - static PyInterpreterState *main_interpreter = NULL; - PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; - if (!main_interpreter) { - main_interpreter = current_interpreter; - } else if (unlikely(main_interpreter != current_interpreter)) - #endif - { - PyErr_SetString( - PyExc_ImportError, - "Interpreter change detected - this module can only be loaded into one interpreter per process."); - return -1; - } - return 0; -} -static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { - PyObject *value = PyObject_GetAttrString(spec, from_name); - int result = 0; - if (likely(value)) { - if (allow_none || value != Py_None) { - result = PyDict_SetItemString(moddict, to_name, value); - } - Py_DECREF(value); - } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - } else { - result = -1; - } - return result; -} -static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { - PyObject *module = NULL, *moddict, *modname; - if (__Pyx_check_single_interpreter()) - return NULL; - if (__pyx_m) - return __Pyx_NewRef(__pyx_m); - modname = PyObject_GetAttrString(spec, "name"); - if (unlikely(!modname)) goto bad; - module = PyModule_NewObject(modname); - Py_DECREF(modname); - if (unlikely(!module)) goto bad; - moddict = PyModule_GetDict(module); - if (unlikely(!moddict)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; - return module; -bad: - Py_XDECREF(module); - return NULL; -} - - -static CYTHON_SMALL_CODE int __pyx_pymod_exec__websocket(PyObject *__pyx_pyinit_module) -#endif +PyMODINIT_FUNC PyInit__websocket(void); /*proto*/ +PyMODINIT_FUNC PyInit__websocket(void) #endif { PyObject *__pyx_t_1 = NULL; __Pyx_RefNannyDeclarations - #if CYTHON_PEP489_MULTI_PHASE_INIT - if (__pyx_m) { - if (__pyx_m == __pyx_pyinit_module) return 0; - PyErr_SetString(PyExc_RuntimeError, "Module '_websocket' has already been imported. Re-initialisation is not supported."); - return -1; + #if CYTHON_REFNANNY + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); + if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); } - #elif PY_MAJOR_VERSION >= 3 - if (__pyx_m) return __Pyx_NewRef(__pyx_m); #endif - #if CYTHON_REFNANNY -__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); -if (!__Pyx_RefNanny) { - PyErr_Clear(); - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); - if (!__Pyx_RefNanny) - Py_FatalError("failed to import 'refnanny' module"); -} -#endif - __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit__websocket(void)", 0); + __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit__websocket(void)", 0); if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #ifdef __Pxy_PyFrame_Initialize_Offsets - __Pxy_PyFrame_Initialize_Offsets(); - #endif __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) @@ -1917,9 +1209,6 @@ if (!__Pyx_RefNanny) { #ifdef __Pyx_Generator_USED if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif - #ifdef __Pyx_AsyncGen_USED - if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif #ifdef __Pyx_StopAsyncIteration_USED if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif @@ -1931,23 +1220,18 @@ if (!__Pyx_RefNanny) { #endif #endif /*--- Module creation code ---*/ - #if CYTHON_PEP489_MULTI_PHASE_INIT - __pyx_m = __pyx_pyinit_module; - Py_INCREF(__pyx_m); - #else #if PY_MAJOR_VERSION < 3 __pyx_m = Py_InitModule4("_websocket", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); #else __pyx_m = PyModule_Create(&__pyx_moduledef); #endif if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) - #endif __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) Py_INCREF(__pyx_d); __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + #if CYTHON_COMPILING_IN_PYPY Py_INCREF(__pyx_b); - __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_cython_runtime); + #endif if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); /*--- Initialize various global constants etc. ---*/ if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) @@ -1955,7 +1239,7 @@ if (!__Pyx_RefNanny) { if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif if (__pyx_module_is_main_aiohttp___websocket) { - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + if (PyObject_SetAttrString(__pyx_m, "__name__", __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) } #if PY_MAJOR_VERSION >= 3 { @@ -1966,17 +1250,25 @@ if (!__Pyx_RefNanny) { } #endif /*--- Builtin init code ---*/ - if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error; + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) /*--- Constants init code ---*/ - if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error; - /*--- Global type/function init code ---*/ - (void)__Pyx_modinit_global_init_code(); - (void)__Pyx_modinit_variable_export_code(); - (void)__Pyx_modinit_function_export_code(); - (void)__Pyx_modinit_type_init_code(); - if (unlikely(__Pyx_modinit_type_import_code() != 0)) goto __pyx_L1_error; - (void)__Pyx_modinit_variable_import_code(); - (void)__Pyx_modinit_function_import_code(); + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global init code ---*/ + /*--- Variable export code ---*/ + /*--- Function export code ---*/ + /*--- Type init code ---*/ + /*--- Type import code ---*/ + __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__Pyx_BUILTIN_MODULE_NAME, "type", + #if CYTHON_COMPILING_IN_PYPY + sizeof(PyTypeObject), + #else + sizeof(PyHeapTypeObject), + #endif + 0); if (unlikely(!__pyx_ptype_7cpython_4type_type)) __PYX_ERR(1, 9, __pyx_L1_error) + __pyx_ptype_7cpython_4bool_bool = __Pyx_ImportType(__Pyx_BUILTIN_MODULE_NAME, "bool", sizeof(PyBoolObject), 0); if (unlikely(!__pyx_ptype_7cpython_4bool_bool)) __PYX_ERR(2, 8, __pyx_L1_error) + __pyx_ptype_7cpython_7complex_complex = __Pyx_ImportType(__Pyx_BUILTIN_MODULE_NAME, "complex", sizeof(PyComplexObject), 0); if (unlikely(!__pyx_ptype_7cpython_7complex_complex)) __PYX_ERR(3, 15, __pyx_L1_error) + /*--- Variable import code ---*/ + /*--- Function import code ---*/ /*--- Execution code ---*/ #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) @@ -1985,8 +1277,8 @@ if (!__Pyx_RefNanny) { /* "aiohttp/_websocket.pyx":9 * from libc.stdint cimport uint32_t, uint64_t, uintmax_t * - * def _websocket_mask_cython(object mask, object data): # <<<<<<<<<<<<<< - * """Note, this function mutates its `data` argument + * def _websocket_mask_cython(bytes mask, bytearray data): # <<<<<<<<<<<<<< + * """Note, this function mutates it's `data` argument * """ */ __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_10_websocket_1_websocket_mask_cython, NULL, __pyx_n_s_aiohttp__websocket); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error) @@ -1999,7 +1291,7 @@ if (!__Pyx_RefNanny) { * * #from cpython cimport PyByteArray_AsString # cython still not exports that */ - __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; @@ -2013,18 +1305,16 @@ if (!__Pyx_RefNanny) { if (__pyx_d) { __Pyx_AddTraceback("init aiohttp._websocket", __pyx_clineno, __pyx_lineno, __pyx_filename); } - Py_CLEAR(__pyx_m); + Py_DECREF(__pyx_m); __pyx_m = 0; } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "init aiohttp._websocket"); } __pyx_L0:; __Pyx_RefNannyFinishContext(); - #if CYTHON_PEP489_MULTI_PHASE_INIT - return (__pyx_m != NULL) ? 0 : -1; - #elif PY_MAJOR_VERSION >= 3 - return __pyx_m; - #else + #if PY_MAJOR_VERSION < 3 return; + #else + return __pyx_m; #endif } @@ -2034,9 +1324,9 @@ if (!__Pyx_RefNanny) { static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { PyObject *m = NULL, *p = NULL; void *r = NULL; - m = PyImport_ImportModule(modname); + m = PyImport_ImportModule((char *)modname); if (!m) goto end; - p = PyObject_GetAttrString(m, "RefNannyAPI"); + p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); if (!p) goto end; r = PyLong_AsVoidPtr(p); end: @@ -2046,20 +1336,6 @@ end: } #endif -/* PyObjectGetAttrStr */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { - PyTypeObject* tp = Py_TYPE(obj); - if (likely(tp->tp_getattro)) - return tp->tp_getattro(obj, attr_name); -#if PY_MAJOR_VERSION < 3 - if (likely(tp->tp_getattr)) - return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); -#endif - return PyObject_GetAttr(obj, attr_name); -} -#endif - /* GetBuiltinName */ static PyObject *__Pyx_GetBuiltinName(PyObject *name) { PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); @@ -2167,429 +1443,81 @@ static int __Pyx_ParseOptionalKeywords( #endif PyUnicode_Compare(**name, key); if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; - if (cmp == 0) { - values[name-argnames] = value; - break; - } - name++; - } - if (*name) continue; - else { - PyObject*** argname = argnames; - while (argname != first_kw_arg) { - int cmp = (**argname == key) ? 0 : - #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 - (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 : - #endif - PyUnicode_Compare(**argname, key); - if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; - if (cmp == 0) goto arg_passed_twice; - argname++; - } - } - } else - goto invalid_keyword_type; - if (kwds2) { - if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; - } else { - goto invalid_keyword; - } - } - return 0; -arg_passed_twice: - __Pyx_RaiseDoubleKeywordsError(function_name, key); - goto bad; -invalid_keyword_type: - PyErr_Format(PyExc_TypeError, - "%.200s() keywords must be strings", function_name); - goto bad; -invalid_keyword: - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION < 3 - "%.200s() got an unexpected keyword argument '%.200s'", - function_name, PyString_AsString(key)); - #else - "%s() got an unexpected keyword argument '%U'", - function_name, key); - #endif -bad: - return -1; -} - -/* PyCFunctionFastCall */ -#if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { - PyCFunctionObject *func = (PyCFunctionObject*)func_obj; - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); - int flags = PyCFunction_GET_FLAGS(func); - assert(PyCFunction_Check(func)); - assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); - assert(nargs >= 0); - assert(nargs == 0 || args != NULL); - /* _PyCFunction_FastCallDict() must not be called with an exception set, - because it may clear it (directly or indirectly) and so the - caller loses its exception */ - assert(!PyErr_Occurred()); - if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { - return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); - } else { - return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); - } -} -#endif - -/* PyFunctionFastCall */ -#if CYTHON_FAST_PYCALL -static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, - PyObject *globals) { - PyFrameObject *f; - PyThreadState *tstate = __Pyx_PyThreadState_Current; - PyObject **fastlocals; - Py_ssize_t i; - PyObject *result; - assert(globals != NULL); - /* XXX Perhaps we should create a specialized - PyFrame_New() that doesn't take locals, but does - take builtins without sanity checking them. - */ - assert(tstate != NULL); - f = PyFrame_New(tstate, co, globals, NULL); - if (f == NULL) { - return NULL; - } - fastlocals = __Pyx_PyFrame_GetLocalsplus(f); - for (i = 0; i < na; i++) { - Py_INCREF(*args); - fastlocals[i] = *args++; - } - result = PyEval_EvalFrameEx(f,0); - ++tstate->recursion_depth; - Py_DECREF(f); - --tstate->recursion_depth; - return result; -} -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { - PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); - PyObject *globals = PyFunction_GET_GLOBALS(func); - PyObject *argdefs = PyFunction_GET_DEFAULTS(func); - PyObject *closure; -#if PY_MAJOR_VERSION >= 3 - PyObject *kwdefs; -#endif - PyObject *kwtuple, **k; - PyObject **d; - Py_ssize_t nd; - Py_ssize_t nk; - PyObject *result; - assert(kwargs == NULL || PyDict_Check(kwargs)); - nk = kwargs ? PyDict_Size(kwargs) : 0; - if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { - return NULL; - } - if ( -#if PY_MAJOR_VERSION >= 3 - co->co_kwonlyargcount == 0 && -#endif - likely(kwargs == NULL || nk == 0) && - co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { - if (argdefs == NULL && co->co_argcount == nargs) { - result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); - goto done; - } - else if (nargs == 0 && argdefs != NULL - && co->co_argcount == Py_SIZE(argdefs)) { - /* function called with no arguments, but all parameters have - a default value: use default values as arguments .*/ - args = &PyTuple_GET_ITEM(argdefs, 0); - result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); - goto done; - } - } - if (kwargs != NULL) { - Py_ssize_t pos, i; - kwtuple = PyTuple_New(2 * nk); - if (kwtuple == NULL) { - result = NULL; - goto done; - } - k = &PyTuple_GET_ITEM(kwtuple, 0); - pos = i = 0; - while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { - Py_INCREF(k[i]); - Py_INCREF(k[i+1]); - i += 2; - } - nk = i / 2; - } - else { - kwtuple = NULL; - k = NULL; - } - closure = PyFunction_GET_CLOSURE(func); -#if PY_MAJOR_VERSION >= 3 - kwdefs = PyFunction_GET_KW_DEFAULTS(func); -#endif - if (argdefs != NULL) { - d = &PyTuple_GET_ITEM(argdefs, 0); - nd = Py_SIZE(argdefs); - } - else { - d = NULL; - nd = 0; - } -#if PY_MAJOR_VERSION >= 3 - result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, - args, (int)nargs, - k, (int)nk, - d, (int)nd, kwdefs, closure); -#else - result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, - args, (int)nargs, - k, (int)nk, - d, (int)nd, closure); -#endif - Py_XDECREF(kwtuple); -done: - Py_LeaveRecursiveCall(); - return result; -} -#endif -#endif - -/* PyObjectCall */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { - PyObject *result; - ternaryfunc call = func->ob_type->tp_call; - if (unlikely(!call)) - return PyObject_Call(func, arg, kw); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = (*call)(func, arg, kw); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* PyObjectCallMethO */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { - PyObject *self, *result; - PyCFunction cfunc; - cfunc = PyCFunction_GET_FUNCTION(func); - self = PyCFunction_GET_SELF(func); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = cfunc(self, arg); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* PyObjectCallOneArg */ -#if CYTHON_COMPILING_IN_CPYTHON -static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { - PyObject *result; - PyObject *args = PyTuple_New(1); - if (unlikely(!args)) return NULL; - Py_INCREF(arg); - PyTuple_SET_ITEM(args, 0, arg); - result = __Pyx_PyObject_Call(func, args, NULL); - Py_DECREF(args); - return result; -} -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { -#if CYTHON_FAST_PYCALL - if (PyFunction_Check(func)) { - return __Pyx_PyFunction_FastCall(func, &arg, 1); - } -#endif - if (likely(PyCFunction_Check(func))) { - if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { - return __Pyx_PyObject_CallMethO(func, arg); -#if CYTHON_FAST_PYCCALL - } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { - return __Pyx_PyCFunction_FastCall(func, &arg, 1); -#endif + if (cmp == 0) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + int cmp = (**argname == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 : + #endif + PyUnicode_Compare(**argname, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + argname++; + } + } + } else + goto invalid_keyword_type; + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; } } - return __Pyx__PyObject_CallOneArg(func, arg); -} -#else -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { - PyObject *result; - PyObject *args = PyTuple_Pack(1, arg); - if (unlikely(!args)) return NULL; - result = __Pyx_PyObject_Call(func, args, NULL); - Py_DECREF(args); - return result; -} -#endif - -/* TypeImport */ -#ifndef __PYX_HAVE_RT_ImportType -#define __PYX_HAVE_RT_ImportType -static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, - size_t size, enum __Pyx_ImportType_CheckSize check_size) -{ - PyObject *result = 0; - char warning[200]; - Py_ssize_t basicsize; -#ifdef Py_LIMITED_API - PyObject *py_basicsize; -#endif - result = PyObject_GetAttrString(module, class_name); - if (!result) - goto bad; - if (!PyType_Check(result)) { - PyErr_Format(PyExc_TypeError, - "%.200s.%.200s is not a type object", - module_name, class_name); - goto bad; - } -#ifndef Py_LIMITED_API - basicsize = ((PyTypeObject *)result)->tp_basicsize; -#else - py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); - if (!py_basicsize) - goto bad; - basicsize = PyLong_AsSsize_t(py_basicsize); - Py_DECREF(py_basicsize); - py_basicsize = 0; - if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) - goto bad; -#endif - if ((size_t)basicsize < size) { - PyErr_Format(PyExc_ValueError, - "%.200s.%.200s size changed, may indicate binary incompatibility. " - "Expected %zd from C header, got %zd from PyObject", - module_name, class_name, size, basicsize); - goto bad; - } - if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { - PyErr_Format(PyExc_ValueError, - "%.200s.%.200s size changed, may indicate binary incompatibility. " - "Expected %zd from C header, got %zd from PyObject", - module_name, class_name, size, basicsize); - goto bad; - } - else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { - PyOS_snprintf(warning, sizeof(warning), - "%s.%s size changed, may indicate binary incompatibility. " - "Expected %zd from C header, got %zd from PyObject", - module_name, class_name, size, basicsize); - if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; - } - return (PyTypeObject *)result; + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif bad: - Py_XDECREF(result); - return NULL; + return -1; } -#endif -/* PyDictVersioning */ -#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { - PyObject **dictptr = NULL; - Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; - if (offset) { -#if CYTHON_COMPILING_IN_CPYTHON - dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); -#else - dictptr = _PyObject_GetDictPtr(obj); -#endif - } - return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +/* ArgTypeTest */ +static void __Pyx_RaiseArgumentTypeInvalid(const char* name, PyObject *obj, PyTypeObject *type) { + PyErr_Format(PyExc_TypeError, + "Argument '%.200s' has incorrect type (expected %.200s, got %.200s)", + name, type->tp_name, Py_TYPE(obj)->tp_name); } -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) +static CYTHON_INLINE int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, + const char *name, int exact) +{ + if (unlikely(!type)) { + PyErr_SetString(PyExc_SystemError, "Missing type object"); return 0; - return obj_dict_version == __Pyx_get_object_dict_version(obj); -} -#endif - -/* PyErrFetchRestore */ -#if CYTHON_FAST_THREAD_STATE -static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { - PyObject *tmp_type, *tmp_value, *tmp_tb; - tmp_type = tstate->curexc_type; - tmp_value = tstate->curexc_value; - tmp_tb = tstate->curexc_traceback; - tstate->curexc_type = type; - tstate->curexc_value = value; - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); -} -static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { - *type = tstate->curexc_type; - *value = tstate->curexc_value; - *tb = tstate->curexc_traceback; - tstate->curexc_type = 0; - tstate->curexc_value = 0; - tstate->curexc_traceback = 0; -} -#endif - -/* CLineInTraceback */ -#ifndef CYTHON_CLINE_IN_TRACEBACK -static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { - PyObject *use_cline; - PyObject *ptype, *pvalue, *ptraceback; -#if CYTHON_COMPILING_IN_CPYTHON - PyObject **cython_runtime_dict; -#endif - if (unlikely(!__pyx_cython_runtime)) { - return c_line; - } - __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); -#if CYTHON_COMPILING_IN_CPYTHON - cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); - if (likely(cython_runtime_dict)) { - __PYX_PY_DICT_LOOKUP_IF_MODIFIED( - use_cline, *cython_runtime_dict, - __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) - } else -#endif - { - PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); - if (use_cline_obj) { - use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; - Py_DECREF(use_cline_obj); - } else { - PyErr_Clear(); - use_cline = NULL; - } } - if (!use_cline) { - c_line = 0; - PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + if (none_allowed && obj == Py_None) return 1; + else if (exact) { + if (likely(Py_TYPE(obj) == type)) return 1; + #if PY_MAJOR_VERSION == 2 + else if ((type == &PyBaseString_Type) && likely(__Pyx_PyBaseString_CheckExact(obj))) return 1; + #endif } - else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { - c_line = 0; + else { + if (likely(PyObject_TypeCheck(obj, type))) return 1; } - __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); - return c_line; + __Pyx_RaiseArgumentTypeInvalid(name, obj, type); + return 0; } -#endif /* CodeObjectCache */ static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { @@ -2731,25 +1659,21 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename) { PyCodeObject *py_code = 0; PyFrameObject *py_frame = 0; - PyThreadState *tstate = __Pyx_PyThreadState_Current; - if (c_line) { - c_line = __Pyx_CLineForTraceback(tstate, c_line); - } - py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + py_code = __pyx_find_code_object(c_line ? c_line : py_line); if (!py_code) { py_code = __Pyx_CreateCodeObjectForTraceback( funcname, c_line, py_line, filename); if (!py_code) goto bad; - __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + __pyx_insert_code_object(c_line ? c_line : py_line, py_code); } py_frame = PyFrame_New( - tstate, /*PyThreadState *tstate,*/ - py_code, /*PyCodeObject *code,*/ - __pyx_d, /*PyObject *globals,*/ - 0 /*PyObject *locals*/ + PyThreadState_GET(), /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ ); if (!py_frame) goto bad; - __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + py_frame->f_lineno = py_line; PyTraceBack_Here(py_frame); bad: Py_XDECREF(py_code); @@ -2758,25 +1682,21 @@ bad: /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; + const long neg_one = (long) -1, const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; if (is_unsigned) { if (sizeof(long) < sizeof(long)) { return PyInt_FromLong((long) value); } else if (sizeof(long) <= sizeof(unsigned long)) { return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif } } else { if (sizeof(long) <= sizeof(long)) { return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif } } { @@ -2811,7 +1731,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { /* CIntFromPy */ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; + const long neg_one = (long) -1, const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -2877,10 +1797,8 @@ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { #endif if (sizeof(long) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif } } else { #if CYTHON_USE_PYLONG_INTERNALS @@ -2947,10 +1865,8 @@ static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { #endif if (sizeof(long) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif } } { @@ -3000,7 +1916,7 @@ raise_neg_overflow: /* CIntFromPy */ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; + const int neg_one = (int) -1, const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; #if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { @@ -3066,10 +1982,8 @@ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { #endif if (sizeof(int) <= sizeof(unsigned long)) { __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif } } else { #if CYTHON_USE_PYLONG_INTERNALS @@ -3136,10 +2050,8 @@ static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { #endif if (sizeof(int) <= sizeof(long)) { __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif } } { @@ -3187,106 +2099,6 @@ raise_neg_overflow: return (int) -1; } -/* FastTypeChecks */ -#if CYTHON_COMPILING_IN_CPYTHON -static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { - while (a) { - a = a->tp_base; - if (a == b) - return 1; - } - return b == &PyBaseObject_Type; -} -static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { - PyObject *mro; - if (a == b) return 1; - mro = a->tp_mro; - if (likely(mro)) { - Py_ssize_t i, n; - n = PyTuple_GET_SIZE(mro); - for (i = 0; i < n; i++) { - if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) - return 1; - } - return 0; - } - return __Pyx_InBases(a, b); -} -#if PY_MAJOR_VERSION == 2 -static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { - PyObject *exception, *value, *tb; - int res; - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ErrFetch(&exception, &value, &tb); - res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; - if (unlikely(res == -1)) { - PyErr_WriteUnraisable(err); - res = 0; - } - if (!res) { - res = PyObject_IsSubclass(err, exc_type2); - if (unlikely(res == -1)) { - PyErr_WriteUnraisable(err); - res = 0; - } - } - __Pyx_ErrRestore(exception, value, tb); - return res; -} -#else -static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { - int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; - if (!res) { - res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); - } - return res; -} -#endif -static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { - Py_ssize_t i, n; - assert(PyExceptionClass_Check(exc_type)); - n = PyTuple_GET_SIZE(tuple); -#if PY_MAJOR_VERSION >= 3 - for (i=0; itp_basicsize; +#else + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if (!strict && (size_t)basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility. Expected %zd, got %zd", + module_name, class_name, basicsize, size); + if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + } + else if ((size_t)basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s has the wrong size, try recompiling. Expected %zd, got %zd", + module_name, class_name, basicsize, size); + goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(py_module); + Py_XDECREF(result); + return NULL; +} +#endif + /* InitStrings */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { while (t->p) { @@ -3329,8 +2224,6 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { #endif if (!*t->p) return -1; - if (PyObject_Hash(*t->p) == -1) - return -1; ++t; } return 0; @@ -3339,57 +2232,50 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); } -static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { +static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) { Py_ssize_t ignore; return __Pyx_PyObject_AsStringAndSize(o, &ignore); } -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT -#if !CYTHON_PEP393_ENABLED -static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { - char* defenc_c; - PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); - if (!defenc) return NULL; - defenc_c = PyBytes_AS_STRING(defenc); +static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if CYTHON_COMPILING_IN_CPYTHON && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { +#if PY_VERSION_HEX < 0x03030000 + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - { - char* end = defenc_c + PyBytes_GET_SIZE(defenc); - char* c; - for (c = defenc_c; c < end; c++) { - if ((unsigned char) (*c) >= 128) { - PyUnicode_AsASCIIString(o); - return NULL; + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } } } - } #endif - *length = PyBytes_GET_SIZE(defenc); - return defenc_c; -} + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; #else -static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { - if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; + if (__Pyx_PyUnicode_READY(o) == -1) return NULL; #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - if (likely(PyUnicode_IS_ASCII(o))) { - *length = PyUnicode_GET_LENGTH(o); - return PyUnicode_AsUTF8(o); - } else { - PyUnicode_AsASCIIString(o); - return NULL; - } + if (PyUnicode_IS_ASCII(o)) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } #else - return PyUnicode_AsUTF8AndSize(o, length); + return PyUnicode_AsUTF8AndSize(o, length); #endif -} -#endif -#endif -static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT - if ( -#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - __Pyx_sys_getdefaultencoding_not_ascii && #endif - PyUnicode_Check(o)) { - return __Pyx_PyUnicode_AsStringAndSize(o, length); } else #endif #if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) @@ -3413,74 +2299,43 @@ static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { if (is_true | (x == Py_False) | (x == Py_None)) return is_true; else return PyObject_IsTrue(x); } -static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { - int retval; - if (unlikely(!x)) return -1; - retval = __Pyx_PyObject_IsTrue(x); - Py_DECREF(x); - return retval; -} -static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { -#if PY_MAJOR_VERSION >= 3 - if (PyLong_Check(result)) { - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "__int__ returned non-int (type %.200s). " - "The ability to return an instance of a strict subclass of int " - "is deprecated, and may be removed in a future version of Python.", - Py_TYPE(result)->tp_name)) { - Py_DECREF(result); - return NULL; - } - return result; - } -#endif - PyErr_Format(PyExc_TypeError, - "__%.4s__ returned non-%.4s (type %.200s)", - type_name, type_name, Py_TYPE(result)->tp_name); - Py_DECREF(result); - return NULL; -} static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { -#if CYTHON_USE_TYPE_SLOTS PyNumberMethods *m; -#endif const char *name = NULL; PyObject *res = NULL; #if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x) || PyLong_Check(x))) + if (PyInt_Check(x) || PyLong_Check(x)) #else - if (likely(PyLong_Check(x))) + if (PyLong_Check(x)) #endif return __Pyx_NewRef(x); -#if CYTHON_USE_TYPE_SLOTS m = Py_TYPE(x)->tp_as_number; - #if PY_MAJOR_VERSION < 3 +#if PY_MAJOR_VERSION < 3 if (m && m->nb_int) { name = "int"; - res = m->nb_int(x); + res = PyNumber_Int(x); } else if (m && m->nb_long) { name = "long"; - res = m->nb_long(x); + res = PyNumber_Long(x); } - #else - if (likely(m && m->nb_int)) { - name = "int"; - res = m->nb_int(x); - } - #endif #else - if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { - res = PyNumber_Int(x); + if (m && m->nb_int) { + name = "int"; + res = PyNumber_Long(x); } #endif - if (likely(res)) { + if (res) { #if PY_MAJOR_VERSION < 3 - if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { + if (!PyInt_Check(res) && !PyLong_Check(res)) { #else - if (unlikely(!PyLong_CheckExact(res))) { + if (!PyLong_Check(res)) { #endif - return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + name, name, Py_TYPE(res)->tp_name); + Py_DECREF(res); + return NULL; } } else if (!PyErr_Occurred()) { @@ -3497,7 +2352,7 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { if (sizeof(Py_ssize_t) >= sizeof(long)) return PyInt_AS_LONG(b); else - return PyInt_AsSsize_t(b); + return PyInt_AsSsize_t(x); } #endif if (likely(PyLong_CheckExact(b))) { @@ -3551,9 +2406,6 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_DECREF(x); return ival; } -static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { - return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); -} static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { return PyInt_FromSize_t(ival); } diff --git a/venv/Lib/site-packages/aiohttp/_websocket.pyx b/venv/Lib/site-packages/aiohttp/_websocket.pyx index e4d992a7..4fc33971 100644 --- a/venv/Lib/site-packages/aiohttp/_websocket.pyx +++ b/venv/Lib/site-packages/aiohttp/_websocket.pyx @@ -6,8 +6,8 @@ cdef extern from "Python.h": from libc.stdint cimport uint32_t, uint64_t, uintmax_t -def _websocket_mask_cython(object mask, object data): - """Note, this function mutates its `data` argument +def _websocket_mask_cython(bytes mask, bytearray data): + """Note, this function mutates it's `data` argument """ cdef: Py_ssize_t data_len, i @@ -19,14 +19,6 @@ def _websocket_mask_cython(object mask, object data): assert len(mask) == 4 - if not isinstance(mask, bytes): - mask = bytes(mask) - - if isinstance(data, bytearray): - data = data - else: - data = bytearray(data) - data_len = len(data) in_buf = PyByteArray_AsString(data) mask_buf = PyBytes_AsString(mask) @@ -52,3 +44,5 @@ def _websocket_mask_cython(object mask, object data): for i in range(0, data_len): in_buf[i] ^= mask_buf[i] + + return data diff --git a/venv/Lib/site-packages/aiohttp/_ws_impl.py b/venv/Lib/site-packages/aiohttp/_ws_impl.py new file mode 100644 index 00000000..27ed5693 --- /dev/null +++ b/venv/Lib/site-packages/aiohttp/_ws_impl.py @@ -0,0 +1,438 @@ +"""WebSocket protocol versions 13 and 8.""" + +import base64 +import binascii +import collections +import hashlib +import json +import os +import random +import sys +from enum import IntEnum +from struct import Struct + +from aiohttp import errors, hdrs +from aiohttp.log import ws_logger + +__all__ = ('WebSocketParser', 'WebSocketWriter', 'do_handshake', + 'WSMessage', 'WebSocketError', 'WSMsgType', 'WSCloseCode') + + +class WSCloseCode(IntEnum): + OK = 1000 + GOING_AWAY = 1001 + PROTOCOL_ERROR = 1002 + UNSUPPORTED_DATA = 1003 + INVALID_TEXT = 1007 + POLICY_VIOLATION = 1008 + MESSAGE_TOO_BIG = 1009 + MANDATORY_EXTENSION = 1010 + INTERNAL_ERROR = 1011 + SERVICE_RESTART = 1012 + TRY_AGAIN_LATER = 1013 + + +ALLOWED_CLOSE_CODES = {int(i) for i in WSCloseCode} + + +class WSMsgType(IntEnum): + CONTINUATION = 0x0 + TEXT = 0x1 + BINARY = 0x2 + PING = 0x9 + PONG = 0xa + CLOSE = 0x8 + CLOSED = 0x101 + ERROR = 0x102 + + text = TEXT + binary = BINARY + ping = PING + pong = PONG + close = CLOSE + closed = CLOSED + error = ERROR + + +WS_KEY = b'258EAFA5-E914-47DA-95CA-C5AB0DC85B11' + + +UNPACK_LEN2 = Struct('!H').unpack_from +UNPACK_LEN3 = Struct('!Q').unpack_from +UNPACK_CLOSE_CODE = Struct('!H').unpack +PACK_LEN1 = Struct('!BB').pack +PACK_LEN2 = Struct('!BBH').pack +PACK_LEN3 = Struct('!BBQ').pack +PACK_CLOSE_CODE = Struct('!H').pack +MSG_SIZE = 2 ** 14 + + +_WSMessageBase = collections.namedtuple('_WSMessageBase', + ['type', 'data', 'extra']) + + +class WSMessage(_WSMessageBase): + def json(self, *, loads=json.loads): + """Return parsed JSON data. + + .. versionadded:: 0.22 + """ + return loads(self.data) + + @property + def tp(self): + return self.type + + +CLOSED_MESSAGE = WSMessage(WSMsgType.CLOSED, None, None) + + +class WebSocketError(Exception): + """WebSocket protocol parser error.""" + + def __init__(self, code, message): + self.code = code + super().__init__(message) + + +def WebSocketParser(out, buf): + while True: + fin, opcode, payload = yield from parse_frame(buf) + + if opcode == WSMsgType.CLOSE: + if len(payload) >= 2: + close_code = UNPACK_CLOSE_CODE(payload[:2])[0] + if close_code < 3000 and close_code not in ALLOWED_CLOSE_CODES: + raise WebSocketError( + WSCloseCode.PROTOCOL_ERROR, + 'Invalid close code: {}'.format(close_code)) + try: + close_message = payload[2:].decode('utf-8') + except UnicodeDecodeError as exc: + raise WebSocketError( + WSCloseCode.INVALID_TEXT, + 'Invalid UTF-8 text message') from exc + msg = WSMessage(WSMsgType.CLOSE, close_code, close_message) + elif payload: + raise WebSocketError( + WSCloseCode.PROTOCOL_ERROR, + 'Invalid close frame: {} {} {!r}'.format( + fin, opcode, payload)) + else: + msg = WSMessage(WSMsgType.CLOSE, 0, '') + + out.feed_data(msg, 0) + + elif opcode == WSMsgType.PING: + out.feed_data(WSMessage(WSMsgType.PING, payload, ''), len(payload)) + + elif opcode == WSMsgType.PONG: + out.feed_data(WSMessage(WSMsgType.PONG, payload, ''), len(payload)) + + elif opcode not in (WSMsgType.TEXT, WSMsgType.BINARY): + raise WebSocketError( + WSCloseCode.PROTOCOL_ERROR, + "Unexpected opcode={!r}".format(opcode)) + else: + # load text/binary + data = [payload] + + while not fin: + fin, _opcode, payload = yield from parse_frame(buf, True) + + # We can receive ping/close in the middle of + # text message, Case 5.* + if _opcode == WSMsgType.PING: + out.feed_data( + WSMessage(WSMsgType.PING, payload, ''), len(payload)) + fin, _opcode, payload = yield from parse_frame(buf, True) + elif _opcode == WSMsgType.CLOSE: + if len(payload) >= 2: + close_code = UNPACK_CLOSE_CODE(payload[:2])[0] + if (close_code not in ALLOWED_CLOSE_CODES and + close_code < 3000): + raise WebSocketError( + WSCloseCode.PROTOCOL_ERROR, + 'Invalid close code: {}'.format(close_code)) + try: + close_message = payload[2:].decode('utf-8') + except UnicodeDecodeError as exc: + raise WebSocketError( + WSCloseCode.INVALID_TEXT, + 'Invalid UTF-8 text message') from exc + msg = WSMessage(WSMsgType.CLOSE, close_code, + close_message) + elif payload: + raise WebSocketError( + WSCloseCode.PROTOCOL_ERROR, + 'Invalid close frame: {} {} {!r}'.format( + fin, opcode, payload)) + else: + msg = WSMessage(WSMsgType.CLOSE, 0, '') + + out.feed_data(msg, 0) + fin, _opcode, payload = yield from parse_frame(buf, True) + + if _opcode != WSMsgType.CONTINUATION: + raise WebSocketError( + WSCloseCode.PROTOCOL_ERROR, + 'The opcode in non-fin frame is expected ' + 'to be zero, got {!r}'.format(_opcode)) + else: + data.append(payload) + + if opcode == WSMsgType.TEXT: + try: + text = b''.join(data).decode('utf-8') + out.feed_data(WSMessage(WSMsgType.TEXT, text, ''), + len(text)) + except UnicodeDecodeError as exc: + raise WebSocketError( + WSCloseCode.INVALID_TEXT, + 'Invalid UTF-8 text message') from exc + else: + data = b''.join(data) + out.feed_data( + WSMessage(WSMsgType.BINARY, data, ''), len(data)) + + +native_byteorder = sys.byteorder + + +def _websocket_mask_python(mask, data): + """Websocket masking function. + + `mask` is a `bytes` object of length 4; `data` is a `bytes` object + of any length. Returns a `bytes` object of the same length as + `data` with the mask applied as specified in section 5.3 of RFC + 6455. + + This pure-python implementation may be replaced by an optimized + version when available. + + """ + assert isinstance(data, bytearray), data + assert len(mask) == 4, mask + datalen = len(data) + if datalen == 0: + # everything work without this, but may be changed later in Python. + return bytearray() + data = int.from_bytes(data, native_byteorder) + mask = int.from_bytes(mask * (datalen // 4) + mask[: datalen % 4], + native_byteorder) + return (data ^ mask).to_bytes(datalen, native_byteorder) + + +if bool(os.environ.get('AIOHTTP_NO_EXTENSIONS')): + _websocket_mask = _websocket_mask_python +else: + try: + from ._websocket import _websocket_mask_cython + _websocket_mask = _websocket_mask_cython + except ImportError: # pragma: no cover + _websocket_mask = _websocket_mask_python + + +def parse_frame(buf, continuation=False): + """Return the next frame from the socket.""" + # read header + data = yield from buf.read(2) + first_byte, second_byte = data + + fin = (first_byte >> 7) & 1 + rsv1 = (first_byte >> 6) & 1 + rsv2 = (first_byte >> 5) & 1 + rsv3 = (first_byte >> 4) & 1 + opcode = first_byte & 0xf + + # frame-fin = %x0 ; more frames of this message follow + # / %x1 ; final frame of this message + # frame-rsv1 = %x0 ; 1 bit, MUST be 0 unless negotiated otherwise + # frame-rsv2 = %x0 ; 1 bit, MUST be 0 unless negotiated otherwise + # frame-rsv3 = %x0 ; 1 bit, MUST be 0 unless negotiated otherwise + if rsv1 or rsv2 or rsv3: + raise WebSocketError( + WSCloseCode.PROTOCOL_ERROR, + 'Received frame with non-zero reserved bits') + + if opcode > 0x7 and fin == 0: + raise WebSocketError( + WSCloseCode.PROTOCOL_ERROR, + 'Received fragmented control frame') + + if fin == 0 and opcode == WSMsgType.CONTINUATION and not continuation: + raise WebSocketError( + WSCloseCode.PROTOCOL_ERROR, + 'Received new fragment frame with non-zero ' + 'opcode {!r}'.format(opcode)) + + has_mask = (second_byte >> 7) & 1 + length = (second_byte) & 0x7f + + # Control frames MUST have a payload length of 125 bytes or less + if opcode > 0x7 and length > 125: + raise WebSocketError( + WSCloseCode.PROTOCOL_ERROR, + "Control frame payload cannot be larger than 125 bytes") + + # read payload + if length == 126: + data = yield from buf.read(2) + length = UNPACK_LEN2(data)[0] + elif length > 126: + data = yield from buf.read(8) + length = UNPACK_LEN3(data)[0] + + if has_mask: + mask = yield from buf.read(4) + + if length: + payload = yield from buf.read(length) + else: + payload = bytearray() + + if has_mask: + payload = _websocket_mask(bytes(mask), payload) + + return fin, opcode, payload + + +class WebSocketWriter: + + def __init__(self, writer, *, use_mask=False, random=random.Random()): + self.writer = writer + self.use_mask = use_mask + self.randrange = random.randrange + + def _send_frame(self, message, opcode): + """Send a frame over the websocket with message as its payload.""" + msg_length = len(message) + + use_mask = self.use_mask + if use_mask: + mask_bit = 0x80 + else: + mask_bit = 0 + + if msg_length < 126: + header = PACK_LEN1(0x80 | opcode, msg_length | mask_bit) + elif msg_length < (1 << 16): + header = PACK_LEN2(0x80 | opcode, 126 | mask_bit, msg_length) + else: + header = PACK_LEN3(0x80 | opcode, 127 | mask_bit, msg_length) + if use_mask: + mask = self.randrange(0, 0xffffffff) + mask = mask.to_bytes(4, 'big') + message = _websocket_mask(mask, bytearray(message)) + self.writer.write(header + mask + message) + else: + if len(message) > MSG_SIZE: + self.writer.write(header) + self.writer.write(message) + else: + self.writer.write(header + message) + + def pong(self, message=b''): + """Send pong message.""" + if isinstance(message, str): + message = message.encode('utf-8') + self._send_frame(message, WSMsgType.PONG) + + def ping(self, message=b''): + """Send ping message.""" + if isinstance(message, str): + message = message.encode('utf-8') + self._send_frame(message, WSMsgType.PING) + + def send(self, message, binary=False): + """Send a frame over the websocket with message as its payload.""" + if isinstance(message, str): + message = message.encode('utf-8') + if binary: + self._send_frame(message, WSMsgType.BINARY) + else: + self._send_frame(message, WSMsgType.TEXT) + + def close(self, code=1000, message=b''): + """Close the websocket, sending the specified code and message.""" + if isinstance(message, str): + message = message.encode('utf-8') + self._send_frame( + PACK_CLOSE_CODE(code) + message, opcode=WSMsgType.CLOSE) + + +def do_handshake(method, headers, transport, protocols=()): + """Prepare WebSocket handshake. + + It return HTTP response code, response headers, websocket parser, + websocket writer. It does not perform any IO. + + `protocols` is a sequence of known protocols. On successful handshake, + the returned response headers contain the first protocol in this list + which the server also knows. + + """ + # WebSocket accepts only GET + if method.upper() != hdrs.METH_GET: + raise errors.HttpProcessingError( + code=405, headers=((hdrs.ALLOW, hdrs.METH_GET),)) + + if 'websocket' != headers.get(hdrs.UPGRADE, '').lower().strip(): + raise errors.HttpBadRequest( + message='No WebSocket UPGRADE hdr: {}\n Can ' + '"Upgrade" only to "WebSocket".'.format(headers.get(hdrs.UPGRADE))) + + if 'upgrade' not in headers.get(hdrs.CONNECTION, '').lower(): + raise errors.HttpBadRequest( + message='No CONNECTION upgrade hdr: {}'.format( + headers.get(hdrs.CONNECTION))) + + # find common sub-protocol between client and server + protocol = None + if hdrs.SEC_WEBSOCKET_PROTOCOL in headers: + req_protocols = [str(proto.strip()) for proto in + headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(',')] + + for proto in req_protocols: + if proto in protocols: + protocol = proto + break + else: + # No overlap found: Return no protocol as per spec + ws_logger.warning( + 'Client protocols %r don’t overlap server-known ones %r', + req_protocols, protocols) + + # check supported version + version = headers.get(hdrs.SEC_WEBSOCKET_VERSION, '') + if version not in ('13', '8', '7'): + raise errors.HttpBadRequest( + message='Unsupported version: {}'.format(version), + headers=((hdrs.SEC_WEBSOCKET_VERSION, '13'),)) + + # check client handshake for validity + key = headers.get(hdrs.SEC_WEBSOCKET_KEY) + try: + if not key or len(base64.b64decode(key)) != 16: + raise errors.HttpBadRequest( + message='Handshake error: {!r}'.format(key)) + except binascii.Error: + raise errors.HttpBadRequest( + message='Handshake error: {!r}'.format(key)) from None + + response_headers = [ + (hdrs.UPGRADE, 'websocket'), + (hdrs.CONNECTION, 'upgrade'), + (hdrs.TRANSFER_ENCODING, 'chunked'), + (hdrs.SEC_WEBSOCKET_ACCEPT, base64.b64encode( + hashlib.sha1(key.encode() + WS_KEY).digest()).decode())] + + if protocol: + response_headers.append((hdrs.SEC_WEBSOCKET_PROTOCOL, protocol)) + + # response code, headers, parser, writer, protocol + return (101, + response_headers, + WebSocketParser, + WebSocketWriter(transport), + protocol) diff --git a/venv/Lib/site-packages/aiohttp/abc.py b/venv/Lib/site-packages/aiohttp/abc.py index 58817c08..bc20b279 100644 --- a/venv/Lib/site-packages/aiohttp/abc.py +++ b/venv/Lib/site-packages/aiohttp/abc.py @@ -1,208 +1,88 @@ import asyncio -import logging +import sys from abc import ABC, abstractmethod -from collections.abc import Sized -from http.cookies import BaseCookie, Morsel # noqa -from typing import ( - TYPE_CHECKING, - Any, - Awaitable, - Callable, - Dict, - Generator, - Iterable, - List, - Optional, - Tuple, -) - -from multidict import CIMultiDict # noqa -from yarl import URL - -from .helpers import get_running_loop -from .typedefs import LooseCookies - -if TYPE_CHECKING: # pragma: no cover - from .web_request import BaseRequest, Request - from .web_response import StreamResponse - from .web_app import Application - from .web_exceptions import HTTPException -else: - BaseRequest = Request = Application = StreamResponse = None - HTTPException = None +from collections.abc import Iterable, Sized +PY_35 = sys.version_info >= (3, 5) -class AbstractRouter(ABC): - - def __init__(self) -> None: - self._frozen = False - - def post_init(self, app: Application) -> None: - """Post init stage. - - Not an abstract method for sake of backward compatibility, - but if the router wants to be aware of the application - it can override this. - """ - - @property - def frozen(self) -> bool: - return self._frozen - def freeze(self) -> None: - """Freeze router.""" - self._frozen = True +class AbstractRouter(ABC): + @asyncio.coroutine # pragma: no branch @abstractmethod - async def resolve(self, request: Request) -> 'AbstractMatchInfo': + def resolve(self, request): """Return MATCH_INFO for given request""" class AbstractMatchInfo(ABC): - @property # pragma: no branch + @asyncio.coroutine # pragma: no branch @abstractmethod - def handler(self) -> Callable[[Request], Awaitable[StreamResponse]]: + def handler(self, request): """Execute matched request handler""" - @property + @asyncio.coroutine # pragma: no branch @abstractmethod - def expect_handler(self) -> Callable[[Request], Awaitable[None]]: + def expect_handler(self, request): """Expect handler for 100-continue processing""" @property # pragma: no branch @abstractmethod - def http_exception(self) -> Optional[HTTPException]: + def http_exception(self): """HTTPException instance raised on router's resolving, or None""" @abstractmethod # pragma: no branch - def get_info(self) -> Dict[str, Any]: + def get_info(self): """Return a dict with additional info useful for introspection""" - @property # pragma: no branch - @abstractmethod - def apps(self) -> Tuple[Application, ...]: - """Stack of nested applications. - - Top level application is left-most element. - - """ - - @abstractmethod - def add_app(self, app: Application) -> None: - """Add application to the nested apps stack.""" - - @abstractmethod - def freeze(self) -> None: - """Freeze the match info. - - The method is called after route resolution. - - After the call .add_app() is forbidden. - - """ - class AbstractView(ABC): - """Abstract class based view.""" - def __init__(self, request: Request) -> None: + def __init__(self, request): self._request = request @property - def request(self) -> Request: - """Request instance.""" + def request(self): return self._request + @asyncio.coroutine # pragma: no branch @abstractmethod - def __await__(self) -> Generator[Any, None, StreamResponse]: - """Execute the view handler.""" + def __iter__(self): + while False: # pragma: no cover + yield None + + if PY_35: # pragma: no branch + @abstractmethod + def __await__(self): + return # pragma: no cover class AbstractResolver(ABC): - """Abstract DNS resolver.""" + @asyncio.coroutine # pragma: no branch @abstractmethod - async def resolve(self, host: str, - port: int, family: int) -> List[Dict[str, Any]]: + def resolve(self, hostname): """Return IP address for given hostname""" + @asyncio.coroutine # pragma: no branch @abstractmethod - async def close(self) -> None: + def close(self): """Release resolver""" -if TYPE_CHECKING: # pragma: no cover - IterableBase = Iterable[Morsel[str]] -else: - IterableBase = Iterable +class AbstractCookieJar(Sized, Iterable): - -class AbstractCookieJar(Sized, IterableBase): - """Abstract Cookie Jar.""" - - def __init__(self, *, - loop: Optional[asyncio.AbstractEventLoop]=None) -> None: - self._loop = get_running_loop(loop) + def __init__(self, *, loop=None): + self._loop = loop or asyncio.get_event_loop() @abstractmethod - def clear(self) -> None: + def clear(self): """Clear all cookies.""" @abstractmethod - def update_cookies(self, - cookies: LooseCookies, - response_url: URL=URL()) -> None: + def update_cookies(self, cookies, response_url=None): """Update cookies.""" @abstractmethod - def filter_cookies(self, request_url: URL) -> 'BaseCookie[str]': + def filter_cookies(self, request_url): """Return the jar's cookies filtered by their attributes.""" - - -class AbstractStreamWriter(ABC): - """Abstract stream writer.""" - - buffer_size = 0 - output_size = 0 - length = 0 # type: Optional[int] - - @abstractmethod - async def write(self, chunk: bytes) -> None: - """Write chunk into stream.""" - - @abstractmethod - async def write_eof(self, chunk: bytes=b'') -> None: - """Write last chunk.""" - - @abstractmethod - async def drain(self) -> None: - """Flush the write buffer.""" - - @abstractmethod - def enable_compression(self, encoding: str='deflate') -> None: - """Enable HTTP body compression""" - - @abstractmethod - def enable_chunking(self) -> None: - """Enable HTTP chunked mode""" - - @abstractmethod - async def write_headers(self, status_line: str, - headers: 'CIMultiDict[str]') -> None: - """Write HTTP headers""" - - -class AbstractAccessLogger(ABC): - """Abstract writer to access log.""" - - def __init__(self, logger: logging.Logger, log_format: str) -> None: - self.logger = logger - self.log_format = log_format - - @abstractmethod - def log(self, - request: BaseRequest, - response: StreamResponse, - time: float) -> None: - """Emit log to logger.""" diff --git a/venv/Lib/site-packages/aiohttp/base_protocol.py b/venv/Lib/site-packages/aiohttp/base_protocol.py deleted file mode 100644 index 331241d9..00000000 --- a/venv/Lib/site-packages/aiohttp/base_protocol.py +++ /dev/null @@ -1,81 +0,0 @@ -import asyncio -from typing import Optional, cast - -from .tcp_helpers import tcp_nodelay - - -class BaseProtocol(asyncio.Protocol): - __slots__ = ('_loop', '_paused', '_drain_waiter', - '_connection_lost', '_reading_paused', 'transport') - - def __init__(self, loop: asyncio.AbstractEventLoop) -> None: - self._loop = loop # type: asyncio.AbstractEventLoop - self._paused = False - self._drain_waiter = None # type: Optional[asyncio.Future[None]] - self._connection_lost = False - self._reading_paused = False - - self.transport = None # type: Optional[asyncio.Transport] - - def pause_writing(self) -> None: - assert not self._paused - self._paused = True - - def resume_writing(self) -> None: - assert self._paused - self._paused = False - - waiter = self._drain_waiter - if waiter is not None: - self._drain_waiter = None - if not waiter.done(): - waiter.set_result(None) - - def pause_reading(self) -> None: - if not self._reading_paused and self.transport is not None: - try: - self.transport.pause_reading() - except (AttributeError, NotImplementedError, RuntimeError): - pass - self._reading_paused = True - - def resume_reading(self) -> None: - if self._reading_paused and self.transport is not None: - try: - self.transport.resume_reading() - except (AttributeError, NotImplementedError, RuntimeError): - pass - self._reading_paused = False - - def connection_made(self, transport: asyncio.BaseTransport) -> None: - tr = cast(asyncio.Transport, transport) - tcp_nodelay(tr, True) - self.transport = tr - - def connection_lost(self, exc: Optional[BaseException]) -> None: - self._connection_lost = True - # Wake up the writer if currently paused. - self.transport = None - if not self._paused: - return - waiter = self._drain_waiter - if waiter is None: - return - self._drain_waiter = None - if waiter.done(): - return - if exc is None: - waiter.set_result(None) - else: - waiter.set_exception(exc) - - async def _drain_helper(self) -> None: - if self._connection_lost: - raise ConnectionResetError('Connection lost') - if not self._paused: - return - waiter = self._drain_waiter - assert waiter is None or waiter.cancelled() - waiter = self._loop.create_future() - self._drain_waiter = waiter - await waiter diff --git a/venv/Lib/site-packages/aiohttp/client.py b/venv/Lib/site-packages/aiohttp/client.py index 6dcff5a2..4c616ef8 100644 --- a/venv/Lib/site-packages/aiohttp/client.py +++ b/venv/Lib/site-packages/aiohttp/client.py @@ -3,221 +3,54 @@ import asyncio import base64 import hashlib -import json import os import sys import traceback +import urllib.parse import warnings -from types import SimpleNamespace, TracebackType -from typing import ( # noqa - Any, - Coroutine, - Generator, - Generic, - Iterable, - List, - Mapping, - Optional, - Set, - Tuple, - Type, - TypeVar, - Union, -) - -import attr + from multidict import CIMultiDict, MultiDict, MultiDictProxy, istr -from yarl import URL - -from . import hdrs, http, payload -from .abc import AbstractCookieJar -from .client_exceptions import ClientConnectionError as ClientConnectionError -from .client_exceptions import ( - ClientConnectorCertificateError as ClientConnectorCertificateError, -) -from .client_exceptions import ClientConnectorError as ClientConnectorError -from .client_exceptions import ( - ClientConnectorSSLError as ClientConnectorSSLError, -) -from .client_exceptions import ClientError as ClientError -from .client_exceptions import ClientHttpProxyError as ClientHttpProxyError -from .client_exceptions import ClientOSError as ClientOSError -from .client_exceptions import ClientPayloadError as ClientPayloadError -from .client_exceptions import ( - ClientProxyConnectionError as ClientProxyConnectionError, -) -from .client_exceptions import ClientResponseError as ClientResponseError -from .client_exceptions import ClientSSLError as ClientSSLError -from .client_exceptions import ContentTypeError as ContentTypeError -from .client_exceptions import InvalidURL as InvalidURL -from .client_exceptions import ServerConnectionError as ServerConnectionError -from .client_exceptions import ( - ServerDisconnectedError as ServerDisconnectedError, -) -from .client_exceptions import ( - ServerFingerprintMismatch as ServerFingerprintMismatch, -) -from .client_exceptions import ServerTimeoutError as ServerTimeoutError -from .client_exceptions import TooManyRedirects as TooManyRedirects -from .client_exceptions import WSServerHandshakeError as WSServerHandshakeError -from .client_reqrep import ClientRequest as ClientRequest -from .client_reqrep import ClientResponse as ClientResponse -from .client_reqrep import Fingerprint as Fingerprint -from .client_reqrep import RequestInfo as RequestInfo -from .client_reqrep import _merge_ssl_params -from .client_ws import ClientWebSocketResponse as ClientWebSocketResponse -from .connector import BaseConnector as BaseConnector -from .connector import NamedPipeConnector as NamedPipeConnector -from .connector import TCPConnector as TCPConnector -from .connector import UnixConnector as UnixConnector + +import aiohttp + +from . import hdrs, helpers +from ._ws_impl import WS_KEY, WebSocketParser, WebSocketWriter +from .client_reqrep import ClientRequest, ClientResponse +from .client_ws import ClientWebSocketResponse from .cookiejar import CookieJar -from .helpers import ( - DEBUG, - PY_36, - BasicAuth, - CeilTimeout, - TimeoutHandle, - get_running_loop, - proxies_from_env, - sentinel, - strip_auth_from_url, -) -from .http import WS_KEY, HttpVersion, WebSocketReader, WebSocketWriter -from .http_websocket import ( # noqa - WSHandshakeError, - WSMessage, - ws_ext_gen, - ws_ext_parse, -) -from .streams import FlowControlDataQueue -from .tracing import Trace, TraceConfig -from .typedefs import JSONEncoder, LooseCookies, LooseHeaders, StrOrURL - -__all__ = ( - # client_exceptions - 'ClientConnectionError', - 'ClientConnectorCertificateError', - 'ClientConnectorError', - 'ClientConnectorSSLError', - 'ClientError', - 'ClientHttpProxyError', - 'ClientOSError', - 'ClientPayloadError', - 'ClientProxyConnectionError', - 'ClientResponseError', - 'ClientSSLError', - 'ContentTypeError', - 'InvalidURL', - 'ServerConnectionError', - 'ServerDisconnectedError', - 'ServerFingerprintMismatch', - 'ServerTimeoutError', - 'TooManyRedirects', - 'WSServerHandshakeError', - # client_reqrep - 'ClientRequest', - 'ClientResponse', - 'Fingerprint', - 'RequestInfo', - # connector - 'BaseConnector', - 'TCPConnector', - 'UnixConnector', - 'NamedPipeConnector', - # client_ws - 'ClientWebSocketResponse', - # client - 'ClientSession', - 'ClientTimeout', - 'request') - - -try: - from ssl import SSLContext -except ImportError: # pragma: no cover - SSLContext = object # type: ignore - - -@attr.s(frozen=True, slots=True) -class ClientTimeout: - total = attr.ib(type=Optional[float], default=None) - connect = attr.ib(type=Optional[float], default=None) - sock_read = attr.ib(type=Optional[float], default=None) - sock_connect = attr.ib(type=Optional[float], default=None) - - # pool_queue_timeout = attr.ib(type=float, default=None) - # dns_resolution_timeout = attr.ib(type=float, default=None) - # socket_connect_timeout = attr.ib(type=float, default=None) - # connection_acquiring_timeout = attr.ib(type=float, default=None) - # new_connection_timeout = attr.ib(type=float, default=None) - # http_header_timeout = attr.ib(type=float, default=None) - # response_body_timeout = attr.ib(type=float, default=None) - - # to create a timeout specific for a single request, either - # - create a completely new one to overwrite the default - # - or use http://www.attrs.org/en/stable/api.html#attr.evolve - # to overwrite the defaults - - -# 5 Minute default read timeout -DEFAULT_TIMEOUT = ClientTimeout(total=5*60) - -_RetType = TypeVar('_RetType') +from .errors import WSServerHandshakeError +from .helpers import Timeout + +__all__ = ('ClientSession', 'request', 'get', 'options', 'head', + 'delete', 'post', 'put', 'patch', 'ws_connect') + +PY_35 = sys.version_info >= (3, 5) class ClientSession: """First-class interface for making HTTP requests.""" - ATTRS = frozenset([ - '_source_traceback', '_connector', - 'requote_redirect_url', '_loop', '_cookie_jar', - '_connector_owner', '_default_auth', - '_version', '_json_serialize', - '_requote_redirect_url', - '_timeout', '_raise_for_status', '_auto_decompress', - '_trust_env', '_default_headers', '_skip_auto_headers', - '_request_class', '_response_class', - '_ws_response_class', '_trace_configs']) - _source_traceback = None + _connector = None - def __init__(self, *, connector: Optional[BaseConnector]=None, - loop: Optional[asyncio.AbstractEventLoop]=None, - cookies: Optional[LooseCookies]=None, - headers: Optional[LooseHeaders]=None, - skip_auto_headers: Optional[Iterable[str]]=None, - auth: Optional[BasicAuth]=None, - json_serialize: JSONEncoder=json.dumps, - request_class: Type[ClientRequest]=ClientRequest, - response_class: Type[ClientResponse]=ClientResponse, - ws_response_class: Type[ClientWebSocketResponse]=ClientWebSocketResponse, # noqa - version: HttpVersion=http.HttpVersion11, - cookie_jar: Optional[AbstractCookieJar]=None, - connector_owner: bool=True, - raise_for_status: bool=False, - read_timeout: Union[float, object]=sentinel, - conn_timeout: Optional[float]=None, - timeout: Union[object, ClientTimeout]=sentinel, - auto_decompress: bool=True, - trust_env: bool=False, - requote_redirect_url: bool=True, - trace_configs: Optional[List[TraceConfig]]=None) -> None: - - if loop is None: - if connector is not None: - loop = connector._loop - - loop = get_running_loop(loop) + def __init__(self, *, connector=None, loop=None, cookies=None, + headers=None, skip_auto_headers=None, + auth=None, request_class=ClientRequest, + response_class=ClientResponse, + ws_response_class=ClientWebSocketResponse, + version=aiohttp.HttpVersion11, + cookie_jar=None): if connector is None: - connector = TCPConnector(loop=loop) - - if connector._loop is not loop: - raise RuntimeError( - "Session and connector has to use same event loop") + connector = aiohttp.TCPConnector(loop=loop) + loop = connector._loop # never None + else: + if loop is None: + loop = connector._loop # never None + elif connector._loop is not loop: + raise ValueError("loop argument must agree with connector") self._loop = loop - if loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1)) @@ -227,48 +60,16 @@ class ClientSession: if cookies is not None: self._cookie_jar.update_cookies(cookies) - - self._connector = connector # type: Optional[BaseConnector] - self._connector_owner = connector_owner + self._connector = connector self._default_auth = auth self._version = version - self._json_serialize = json_serialize - if timeout is sentinel: - self._timeout = DEFAULT_TIMEOUT - if read_timeout is not sentinel: - warnings.warn("read_timeout is deprecated, " - "use timeout argument instead", - DeprecationWarning, - stacklevel=2) - self._timeout = attr.evolve(self._timeout, total=read_timeout) - if conn_timeout is not None: - self._timeout = attr.evolve(self._timeout, - connect=conn_timeout) - warnings.warn("conn_timeout is deprecated, " - "use timeout argument instead", - DeprecationWarning, - stacklevel=2) - else: - self._timeout = timeout # type: ignore - if read_timeout is not sentinel: - raise ValueError("read_timeout and timeout parameters " - "conflict, please setup " - "timeout.read") - if conn_timeout is not None: - raise ValueError("conn_timeout and timeout parameters " - "conflict, please setup " - "timeout.connect") - self._raise_for_status = raise_for_status - self._auto_decompress = auto_decompress - self._trust_env = trust_env - self._requote_redirect_url = requote_redirect_url # Convert to list of tuples if headers: - real_headers = CIMultiDict(headers) # type: CIMultiDict[str] + headers = CIMultiDict(headers) else: - real_headers = CIMultiDict() - self._default_headers = real_headers # type: CIMultiDict[str] + headers = CIMultiDict() + self._default_headers = headers if skip_auto_headers is not None: self._skip_auto_headers = frozenset([istr(i) for i in skip_auto_headers]) @@ -279,478 +80,264 @@ class ClientSession: self._response_class = response_class self._ws_response_class = ws_response_class - self._trace_configs = trace_configs or [] - for trace_config in self._trace_configs: - trace_config.freeze() - - def __init_subclass__(cls: Type['ClientSession']) -> None: - warnings.warn("Inheritance class {} from ClientSession " - "is discouraged".format(cls.__name__), - DeprecationWarning, - stacklevel=2) - - if DEBUG: - def __setattr__(self, name: str, val: Any) -> None: - if name not in self.ATTRS: - warnings.warn("Setting custom ClientSession.{} attribute " - "is discouraged".format(name), - DeprecationWarning, - stacklevel=2) - super().__setattr__(name, val) - - def __del__(self, _warnings: Any=warnings) -> None: + def __del__(self, _warnings=warnings): if not self.closed: - if PY_36: - kwargs = {'source': self} - else: - kwargs = {} + self.close() + _warnings.warn("Unclosed client session {!r}".format(self), - ResourceWarning, - **kwargs) + ResourceWarning) context = {'client_session': self, 'message': 'Unclosed client session'} if self._source_traceback is not None: context['source_traceback'] = self._source_traceback self._loop.call_exception_handler(context) - def request(self, - method: str, - url: StrOrURL, - **kwargs: Any) -> '_RequestContextManager': + def request(self, method, url, *, + params=None, + data=None, + headers=None, + skip_auto_headers=None, + auth=None, + allow_redirects=True, + max_redirects=10, + encoding='utf-8', + version=None, + compress=None, + chunked=None, + expect100=False, + read_until_eof=True, + proxy=None, + proxy_auth=None, + timeout=5*60): """Perform HTTP request.""" - return _RequestContextManager(self._request(method, url, **kwargs)) - - async def _request( - self, - method: str, - str_or_url: StrOrURL, *, - params: Optional[Mapping[str, str]]=None, - data: Any=None, - json: Any=None, - cookies: Optional[LooseCookies]=None, - headers: LooseHeaders=None, - skip_auto_headers: Optional[Iterable[str]]=None, - auth: Optional[BasicAuth]=None, - allow_redirects: bool=True, - max_redirects: int=10, - compress: Optional[str]=None, - chunked: Optional[bool]=None, - expect100: bool=False, - raise_for_status: Optional[bool]=None, - read_until_eof: bool=True, - proxy: Optional[StrOrURL]=None, - proxy_auth: Optional[BasicAuth]=None, - timeout: Union[ClientTimeout, object]=sentinel, - verify_ssl: Optional[bool]=None, - fingerprint: Optional[bytes]=None, - ssl_context: Optional[SSLContext]=None, - ssl: Optional[Union[SSLContext, bool, Fingerprint]]=None, - proxy_headers: Optional[LooseHeaders]=None, - trace_request_ctx: Optional[SimpleNamespace]=None - ) -> ClientResponse: - - # NOTE: timeout clamps existing connect and read timeouts. We cannot - # set the default to None because we need to detect if the user wants - # to use the existing timeouts by setting timeout to None. + + return _RequestContextManager( + self._request( + method, + url, + params=params, + data=data, + headers=headers, + skip_auto_headers=skip_auto_headers, + auth=auth, + allow_redirects=allow_redirects, + max_redirects=max_redirects, + encoding=encoding, + version=version, + compress=compress, + chunked=chunked, + expect100=expect100, + read_until_eof=read_until_eof, + proxy=proxy, + proxy_auth=proxy_auth, + timeout=timeout)) + + @asyncio.coroutine + def _request(self, method, url, *, + params=None, + data=None, + headers=None, + skip_auto_headers=None, + auth=None, + allow_redirects=True, + max_redirects=10, + encoding='utf-8', + version=None, + compress=None, + chunked=None, + expect100=False, + read_until_eof=True, + proxy=None, + proxy_auth=None, + timeout=5*60): + + if version is not None: + warnings.warn("HTTP version should be specified " + "by ClientSession constructor", DeprecationWarning) + else: + version = self._version if self.closed: raise RuntimeError('Session is closed') - ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint) - - if data is not None and json is not None: - raise ValueError( - 'data and json parameters can not be used at the same time') - elif json is not None: - data = payload.JsonPayload(json, dumps=self._json_serialize) - - if not isinstance(chunked, bool) and chunked is not None: - warnings.warn( - 'Chunk size is deprecated #1615', DeprecationWarning) - redirects = 0 history = [] - version = self._version # Merge with default headers and transform to CIMultiDict headers = self._prepare_headers(headers) - proxy_headers = self._prepare_headers(proxy_headers) - - try: - url = URL(str_or_url) - except ValueError: - raise InvalidURL(str_or_url) + if auth is None: + auth = self._default_auth + # It would be confusing if we support explicit Authorization header + # with `auth` argument + if (headers is not None and + auth is not None and + hdrs.AUTHORIZATION in headers): + raise ValueError("Can't combine `Authorization` header with " + "`auth` argument") skip_headers = set(self._skip_auto_headers) if skip_auto_headers is not None: for i in skip_auto_headers: skip_headers.add(istr(i)) - if proxy is not None: - try: - proxy = URL(proxy) - except ValueError: - raise InvalidURL(proxy) + while True: + url, _ = urllib.parse.urldefrag(url) - if timeout is sentinel: - real_timeout = self._timeout # type: ClientTimeout - else: - if not isinstance(timeout, ClientTimeout): - real_timeout = ClientTimeout(total=timeout) # type: ignore - else: - real_timeout = timeout - # timeout is cumulative for all request operations - # (request, redirects, responses, data consuming) - tm = TimeoutHandle(self._loop, real_timeout.total) - handle = tm.start() - - traces = [ - Trace( - self, - trace_config, - trace_config.trace_config_ctx( - trace_request_ctx=trace_request_ctx) - ) - for trace_config in self._trace_configs - ] - - for trace in traces: - await trace.send_request_start( - method, - url, - headers - ) + cookies = self._cookie_jar.filter_cookies(url) - timer = tm.timer() - try: - with timer: - while True: - url, auth_from_url = strip_auth_from_url(url) - if auth and auth_from_url: - raise ValueError("Cannot combine AUTH argument with " - "credentials encoded in URL") - - if auth is None: - auth = auth_from_url - if auth is None: - auth = self._default_auth - # It would be confusing if we support explicit - # Authorization header with auth argument - if (headers is not None and - auth is not None and - hdrs.AUTHORIZATION in headers): - raise ValueError("Cannot combine AUTHORIZATION header " - "with AUTH argument or credentials " - "encoded in URL") - - all_cookies = self._cookie_jar.filter_cookies(url) - - if cookies is not None: - tmp_cookie_jar = CookieJar() - tmp_cookie_jar.update_cookies(cookies) - req_cookies = tmp_cookie_jar.filter_cookies(url) - if req_cookies: - all_cookies.load(req_cookies) - - if proxy is not None: - proxy = URL(proxy) - elif self._trust_env: - for scheme, proxy_info in proxies_from_env().items(): - if scheme == url.scheme: - proxy = proxy_info.proxy - proxy_auth = proxy_info.proxy_auth - break - - req = self._request_class( - method, url, params=params, headers=headers, - skip_auto_headers=skip_headers, data=data, - cookies=all_cookies, auth=auth, version=version, - compress=compress, chunked=chunked, - expect100=expect100, loop=self._loop, - response_class=self._response_class, - proxy=proxy, proxy_auth=proxy_auth, timer=timer, - session=self, - ssl=ssl, proxy_headers=proxy_headers, traces=traces) - - # connection timeout - try: - with CeilTimeout(real_timeout.connect, - loop=self._loop): - assert self._connector is not None - conn = await self._connector.connect( - req, - traces=traces, - timeout=real_timeout - ) - except asyncio.TimeoutError as exc: - raise ServerTimeoutError( - 'Connection timeout ' - 'to host {0}'.format(url)) from exc - - assert conn.transport is not None - - assert conn.protocol is not None - conn.protocol.set_response_params( - timer=timer, - skip_payload=method.upper() == 'HEAD', - read_until_eof=read_until_eof, - auto_decompress=self._auto_decompress, - read_timeout=real_timeout.sock_read) - - try: - try: - resp = await req.send(conn) - try: - await resp.start(conn) - except BaseException: - resp.close() - raise - except BaseException: - conn.close() - raise - except ClientError: - raise - except OSError as exc: - raise ClientOSError(*exc.args) from exc - - self._cookie_jar.update_cookies(resp.cookies, resp.url) - - # redirects - if resp.status in ( - 301, 302, 303, 307, 308) and allow_redirects: - - for trace in traces: - await trace.send_request_redirect( - method, - url, - headers, - resp - ) - - redirects += 1 - history.append(resp) - if max_redirects and redirects >= max_redirects: - resp.close() - raise TooManyRedirects( - history[0].request_info, tuple(history)) - - # For 301 and 302, mimic IE, now changed in RFC - # https://github.com/kennethreitz/requests/pull/269 - if (resp.status == 303 and - resp.method != hdrs.METH_HEAD) \ - or (resp.status in (301, 302) and - resp.method == hdrs.METH_POST): - method = hdrs.METH_GET - data = None - if headers.get(hdrs.CONTENT_LENGTH): - headers.pop(hdrs.CONTENT_LENGTH) - - r_url = (resp.headers.get(hdrs.LOCATION) or - resp.headers.get(hdrs.URI)) - if r_url is None: - # see github.com/aio-libs/aiohttp/issues/2022 - break - else: - # reading from correct redirection - # response is forbidden - resp.release() - - try: - r_url = URL( - r_url, encoded=not self._requote_redirect_url) - - except ValueError: - raise InvalidURL(r_url) - - scheme = r_url.scheme - if scheme not in ('http', 'https', ''): - resp.close() - raise ValueError( - 'Can redirect only to http or https') - elif not scheme: - r_url = url.join(r_url) - - if url.origin() != r_url.origin(): - auth = None - headers.pop(hdrs.AUTHORIZATION, None) - - url = r_url - params = None - resp.release() - continue + req = self._request_class( + method, url, params=params, headers=headers, + skip_auto_headers=skip_headers, data=data, + cookies=cookies, encoding=encoding, + auth=auth, version=version, compress=compress, chunked=chunked, + expect100=expect100, + loop=self._loop, response_class=self._response_class, + proxy=proxy, proxy_auth=proxy_auth, timeout=timeout) + with Timeout(timeout, loop=self._loop): + conn = yield from self._connector.connect(req) + try: + resp = req.send(conn.writer, conn.reader) + try: + yield from resp.start(conn, read_until_eof) + except: + resp.close() + conn.close() + raise + except (aiohttp.HttpProcessingError, + aiohttp.ServerDisconnectedError) as exc: + raise aiohttp.ClientResponseError() from exc + except OSError as exc: + raise aiohttp.ClientOSError(*exc.args) from exc + + self._cookie_jar.update_cookies(resp.cookies, resp.url) + + # redirects + if resp.status in (301, 302, 303, 307) and allow_redirects: + redirects += 1 + history.append(resp) + if max_redirects and redirects >= max_redirects: + resp.close() break - - # check response status - if raise_for_status is None: - raise_for_status = self._raise_for_status - if raise_for_status: - resp.raise_for_status() - - # register connection - if handle is not None: - if resp.connection is not None: - resp.connection.add_callback(handle.cancel) else: - handle.cancel() - - resp._history = tuple(history) - - for trace in traces: - await trace.send_request_end( - method, - url, - headers, - resp - ) - return resp - - except BaseException as e: - # cleanup timer - tm.close() - if handle: - handle.cancel() - handle = None - - for trace in traces: - await trace.send_request_exception( - method, - url, - headers, - e - ) - raise - - def ws_connect( - self, - url: StrOrURL, *, - method: str=hdrs.METH_GET, - protocols: Iterable[str]=(), - timeout: float=10.0, - receive_timeout: Optional[float]=None, - autoclose: bool=True, - autoping: bool=True, - heartbeat: Optional[float]=None, - auth: Optional[BasicAuth]=None, - origin: Optional[str]=None, - headers: Optional[LooseHeaders]=None, - proxy: Optional[StrOrURL]=None, - proxy_auth: Optional[BasicAuth]=None, - ssl: Union[SSLContext, bool, None, Fingerprint]=None, - verify_ssl: Optional[bool]=None, - fingerprint: Optional[bytes]=None, - ssl_context: Optional[SSLContext]=None, - proxy_headers: Optional[LooseHeaders]=None, - compress: int=0, - max_msg_size: int=4*1024*1024) -> '_WSRequestContextManager': + # TODO: close the connection if BODY is large enough + # Redirect with big BODY is forbidden by HTTP protocol + # but malformed server may send illegal response. + # Small BODIES with text like "Not Found" are still + # perfectly fine and should be accepted. + yield from resp.release() + + # For 301 and 302, mimic IE behaviour, now changed in RFC. + # Details: https://github.com/kennethreitz/requests/pull/269 + if (resp.status == 303 and resp.method != hdrs.METH_HEAD) \ + or (resp.status in (301, 302) and + resp.method == hdrs.METH_POST): + method = hdrs.METH_GET + data = None + if headers.get(hdrs.CONTENT_LENGTH): + headers.pop(hdrs.CONTENT_LENGTH) + + r_url = (resp.headers.get(hdrs.LOCATION) or + resp.headers.get(hdrs.URI)) + + scheme = urllib.parse.urlsplit(r_url)[0] + if scheme not in ('http', 'https', ''): + resp.close() + raise ValueError('Can redirect only to http or https') + elif not scheme: + r_url = urllib.parse.urljoin(url, r_url) + + url = r_url + params = None + yield from resp.release() + continue + + break + + resp._history = tuple(history) + return resp + + def ws_connect(self, url, *, + protocols=(), + timeout=10.0, + autoclose=True, + autoping=True, + auth=None, + origin=None, + headers=None, + proxy=None, + proxy_auth=None): """Initiate websocket connection.""" return _WSRequestContextManager( self._ws_connect(url, - method=method, protocols=protocols, timeout=timeout, - receive_timeout=receive_timeout, autoclose=autoclose, autoping=autoping, - heartbeat=heartbeat, auth=auth, origin=origin, headers=headers, proxy=proxy, - proxy_auth=proxy_auth, - ssl=ssl, - verify_ssl=verify_ssl, - fingerprint=fingerprint, - ssl_context=ssl_context, - proxy_headers=proxy_headers, - compress=compress, - max_msg_size=max_msg_size)) - - async def _ws_connect( - self, - url: StrOrURL, *, - method: str=hdrs.METH_GET, - protocols: Iterable[str]=(), - timeout: float=10.0, - receive_timeout: Optional[float]=None, - autoclose: bool=True, - autoping: bool=True, - heartbeat: Optional[float]=None, - auth: Optional[BasicAuth]=None, - origin: Optional[str]=None, - headers: Optional[LooseHeaders]=None, - proxy: Optional[StrOrURL]=None, - proxy_auth: Optional[BasicAuth]=None, - ssl: Union[SSLContext, bool, None, Fingerprint]=None, - verify_ssl: Optional[bool]=None, - fingerprint: Optional[bytes]=None, - ssl_context: Optional[SSLContext]=None, - proxy_headers: Optional[LooseHeaders]=None, - compress: int=0, - max_msg_size: int=4*1024*1024 - ) -> ClientWebSocketResponse: + proxy_auth=proxy_auth)) + + @asyncio.coroutine + def _ws_connect(self, url, *, + protocols=(), + timeout=10.0, + autoclose=True, + autoping=True, + auth=None, + origin=None, + headers=None, + proxy=None, + proxy_auth=None): + + sec_key = base64.b64encode(os.urandom(16)) if headers is None: - real_headers = CIMultiDict() # type: CIMultiDict[str] - else: - real_headers = CIMultiDict(headers) + headers = CIMultiDict() default_headers = { hdrs.UPGRADE: hdrs.WEBSOCKET, hdrs.CONNECTION: hdrs.UPGRADE, hdrs.SEC_WEBSOCKET_VERSION: '13', + hdrs.SEC_WEBSOCKET_KEY: sec_key.decode(), } for key, value in default_headers.items(): - real_headers.setdefault(key, value) - - sec_key = base64.b64encode(os.urandom(16)) - real_headers[hdrs.SEC_WEBSOCKET_KEY] = sec_key.decode() + if key not in headers: + headers[key] = value if protocols: - real_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ','.join(protocols) + headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = ','.join(protocols) if origin is not None: - real_headers[hdrs.ORIGIN] = origin - if compress: - extstr = ws_ext_gen(compress=compress) - real_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = extstr - - ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, fingerprint) + headers[hdrs.ORIGIN] = origin # send request - resp = await self.request(method, url, - headers=real_headers, - read_until_eof=False, - auth=auth, - proxy=proxy, - proxy_auth=proxy_auth, - ssl=ssl, - proxy_headers=proxy_headers) + resp = yield from self.get(url, headers=headers, + read_until_eof=False, + auth=auth, + proxy=proxy, + proxy_auth=proxy_auth) try: # check handshake if resp.status != 101: raise WSServerHandshakeError( - resp.request_info, - resp.history, message='Invalid response status', - status=resp.status, + code=resp.status, headers=resp.headers) if resp.headers.get(hdrs.UPGRADE, '').lower() != 'websocket': raise WSServerHandshakeError( - resp.request_info, - resp.history, message='Invalid upgrade header', - status=resp.status, + code=resp.status, headers=resp.headers) if resp.headers.get(hdrs.CONNECTION, '').lower() != 'upgrade': raise WSServerHandshakeError( - resp.request_info, - resp.history, message='Invalid connection header', - status=resp.status, + code=resp.status, headers=resp.headers) # key calculation @@ -759,10 +346,8 @@ class ClientSession: hashlib.sha1(sec_key + WS_KEY).digest()).decode() if key != match: raise WSServerHandshakeError( - resp.request_info, - resp.history, message='Invalid challenge response', - status=resp.status, + code=resp.status, headers=resp.headers) # websocket protocol @@ -777,37 +362,10 @@ class ClientSession: protocol = proto break - # websocket compress - notakeover = False - if compress: - compress_hdrs = resp.headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS) - if compress_hdrs: - try: - compress, notakeover = ws_ext_parse(compress_hdrs) - except WSHandshakeError as exc: - raise WSServerHandshakeError( - resp.request_info, - resp.history, - message=exc.args[0], - status=resp.status, - headers=resp.headers) - else: - compress = 0 - notakeover = False - - conn = resp.connection - assert conn is not None - proto = conn.protocol - assert proto is not None - transport = conn.transport - assert transport is not None - reader = FlowControlDataQueue( - proto, limit=2 ** 16, loop=self._loop) # type: FlowControlDataQueue[WSMessage] # noqa - proto.set_parser(WebSocketReader(reader, max_msg_size), reader) - writer = WebSocketWriter( - proto, transport, use_mask=True, - compress=compress, notakeover=notakeover) - except BaseException: + reader = resp.connection.reader.set_parser(WebSocketParser) + resp.connection.writer.set_tcp_nodelay(True) + writer = WebSocketWriter(resp.connection.writer, use_mask=True) + except Exception: resp.close() raise else: @@ -818,15 +376,9 @@ class ClientSession: timeout, autoclose, autoping, - self._loop, - receive_timeout=receive_timeout, - heartbeat=heartbeat, - compress=compress, - client_notakeover=notakeover) - - def _prepare_headers( - self, - headers: Optional[LooseHeaders]) -> 'CIMultiDict[str]': + self._loop) + + def _prepare_headers(self, headers): """ Add default headers and transform it to CIMultiDict """ # Convert headers to MultiDict @@ -834,7 +386,7 @@ class ClientSession: if headers: if not isinstance(headers, (MultiDictProxy, MultiDict)): headers = CIMultiDict(headers) - added_names = set() # type: Set[str] + added_names = set() for key, value in headers.items(): if key in added_names: result.add(key, value) @@ -843,72 +395,68 @@ class ClientSession: added_names.add(key) return result - def get(self, url: StrOrURL, *, allow_redirects: bool=True, - **kwargs: Any) -> '_RequestContextManager': + def get(self, url, *, allow_redirects=True, **kwargs): """Perform HTTP GET request.""" return _RequestContextManager( self._request(hdrs.METH_GET, url, allow_redirects=allow_redirects, **kwargs)) - def options(self, url: StrOrURL, *, allow_redirects: bool=True, - **kwargs: Any) -> '_RequestContextManager': + def options(self, url, *, allow_redirects=True, **kwargs): """Perform HTTP OPTIONS request.""" return _RequestContextManager( self._request(hdrs.METH_OPTIONS, url, allow_redirects=allow_redirects, **kwargs)) - def head(self, url: StrOrURL, *, allow_redirects: bool=False, - **kwargs: Any) -> '_RequestContextManager': + def head(self, url, *, allow_redirects=False, **kwargs): """Perform HTTP HEAD request.""" return _RequestContextManager( self._request(hdrs.METH_HEAD, url, allow_redirects=allow_redirects, **kwargs)) - def post(self, url: StrOrURL, - *, data: Any=None, **kwargs: Any) -> '_RequestContextManager': + def post(self, url, *, data=None, **kwargs): """Perform HTTP POST request.""" return _RequestContextManager( self._request(hdrs.METH_POST, url, data=data, **kwargs)) - def put(self, url: StrOrURL, - *, data: Any=None, **kwargs: Any) -> '_RequestContextManager': + def put(self, url, *, data=None, **kwargs): """Perform HTTP PUT request.""" return _RequestContextManager( self._request(hdrs.METH_PUT, url, data=data, **kwargs)) - def patch(self, url: StrOrURL, - *, data: Any=None, **kwargs: Any) -> '_RequestContextManager': + def patch(self, url, *, data=None, **kwargs): """Perform HTTP PATCH request.""" return _RequestContextManager( self._request(hdrs.METH_PATCH, url, data=data, **kwargs)) - def delete(self, url: StrOrURL, **kwargs: Any) -> '_RequestContextManager': + def delete(self, url, **kwargs): """Perform HTTP DELETE request.""" return _RequestContextManager( self._request(hdrs.METH_DELETE, url, **kwargs)) - async def close(self) -> None: + def close(self): """Close underlying connector. Release all acquired resources. """ if not self.closed: - if self._connector is not None and self._connector_owner: - await self._connector.close() + self._connector.close() self._connector = None + ret = helpers.create_future(self._loop) + ret.set_result(None) + return ret @property - def closed(self) -> bool: + def closed(self): """Is client session closed. A readonly property. @@ -916,186 +464,202 @@ class ClientSession: return self._connector is None or self._connector.closed @property - def connector(self) -> Optional[BaseConnector]: + def connector(self): """Connector instance used for the session.""" return self._connector @property - def cookie_jar(self) -> AbstractCookieJar: + def cookie_jar(self): """The session cookies.""" return self._cookie_jar @property - def version(self) -> Tuple[int, int]: + def version(self): """The session HTTP protocol version.""" return self._version @property - def requote_redirect_url(self) -> bool: - """Do URL requoting on redirection handling.""" - return self._requote_redirect_url - - @requote_redirect_url.setter - def requote_redirect_url(self, val: bool) -> None: - """Do URL requoting on redirection handling.""" - warnings.warn("session.requote_redirect_url modification " - "is deprecated #2778", - DeprecationWarning, - stacklevel=2) - self._requote_redirect_url = val - - @property - def loop(self) -> asyncio.AbstractEventLoop: + def loop(self): """Session's loop.""" - warnings.warn("client.loop property is deprecated", - DeprecationWarning, - stacklevel=2) return self._loop - def detach(self) -> None: + def detach(self): """Detach connector from session without closing the former. Session is switched to closed state anyway. """ self._connector = None - def __enter__(self) -> None: - raise TypeError("Use async with instead") + def __enter__(self): + warnings.warn("Use async with instead", DeprecationWarning) + return self - def __exit__(self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType]) -> None: - # __exit__ should exist in pair with __enter__ but never executed - pass # pragma: no cover + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() - async def __aenter__(self) -> 'ClientSession': - return self + if PY_35: + @asyncio.coroutine + def __aenter__(self): + return self - async def __aexit__(self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType]) -> None: - await self.close() + @asyncio.coroutine + def __aexit__(self, exc_type, exc_val, exc_tb): + yield from self.close() +if PY_35: + from collections.abc import Coroutine + base = Coroutine +else: + base = object -class _BaseRequestContextManager(Coroutine[Any, - Any, - _RetType], - Generic[_RetType]): + +class _BaseRequestContextManager(base): __slots__ = ('_coro', '_resp') - def __init__( - self, - coro: Coroutine['asyncio.Future[Any]', None, _RetType] - ) -> None: + def __init__(self, coro): self._coro = coro + self._resp = None - def send(self, arg: None) -> 'asyncio.Future[Any]': - return self._coro.send(arg) + def send(self, value): + return self._coro.send(value) - def throw(self, arg: BaseException) -> None: # type: ignore - self._coro.throw(arg) # type: ignore + def throw(self, typ, val=None, tb=None): + if val is None: + return self._coro.throw(typ) + elif tb is None: + return self._coro.throw(typ, val) + else: + return self._coro.throw(typ, val, tb) - def close(self) -> None: + def close(self): return self._coro.close() - def __await__(self) -> Generator[Any, None, _RetType]: - ret = self._coro.__await__() - return ret + @property + def gi_frame(self): + return self._coro.gi_frame - def __iter__(self) -> Generator[Any, None, _RetType]: - return self.__await__() + @property + def gi_running(self): + return self._coro.gi_running - async def __aenter__(self) -> _RetType: - self._resp = await self._coro - return self._resp + @property + def gi_code(self): + return self._coro.gi_code + def __next__(self): + return self.send(None) -class _RequestContextManager(_BaseRequestContextManager[ClientResponse]): - async def __aexit__(self, - exc_type: Optional[Type[BaseException]], - exc: Optional[BaseException], - tb: Optional[TracebackType]) -> None: - # We're basing behavior on the exception as it can be caused by - # user code unrelated to the status of the connection. If you - # would like to close a connection you must do that - # explicitly. Otherwise connection error handling should kick in - # and close/recycle the connection as required. - self._resp.release() + @asyncio.coroutine + def __iter__(self): + resp = yield from self._coro + return resp + if PY_35: + def __await__(self): + resp = yield from self._coro + return resp -class _WSRequestContextManager(_BaseRequestContextManager[ - ClientWebSocketResponse]): - async def __aexit__(self, - exc_type: Optional[Type[BaseException]], - exc: Optional[BaseException], - tb: Optional[TracebackType]) -> None: - await self._resp.close() + @asyncio.coroutine + def __aenter__(self): + self._resp = yield from self._coro + return self._resp -class _SessionRequestContextManager: +if not PY_35: + try: + from asyncio import coroutines + coroutines._COROUTINE_TYPES += (_BaseRequestContextManager,) + except: # pragma: no cover + pass # Python 3.4.2 and 3.4.3 has no coroutines._COROUTINE_TYPES - __slots__ = ('_coro', '_resp', '_session') - def __init__(self, - coro: Coroutine['asyncio.Future[Any]', None, ClientResponse], - session: ClientSession) -> None: - self._coro = coro - self._resp = None # type: Optional[ClientResponse] +class _RequestContextManager(_BaseRequestContextManager): + if PY_35: + @asyncio.coroutine + def __aexit__(self, exc_type, exc, tb): + if exc_type is not None: + self._resp.close() + else: + yield from self._resp.release() + + +class _WSRequestContextManager(_BaseRequestContextManager): + if PY_35: + @asyncio.coroutine + def __aexit__(self, exc_type, exc, tb): + yield from self._resp.close() + + +class _DetachedRequestContextManager(_RequestContextManager): + + __slots__ = _RequestContextManager.__slots__ + ('_session', ) + + def __init__(self, coro, session): + super().__init__(coro) self._session = session - async def __aenter__(self) -> ClientResponse: + @asyncio.coroutine + def __iter__(self): try: - self._resp = await self._coro - except BaseException: - await self._session.close() + return (yield from self._coro) + except: + yield from self._session.close() raise - else: - return self._resp - async def __aexit__(self, - exc_type: Optional[Type[BaseException]], - exc: Optional[BaseException], - tb: Optional[TracebackType]) -> None: - assert self._resp is not None - self._resp.close() - await self._session.close() - - -def request( - method: str, - url: StrOrURL, *, - params: Optional[Mapping[str, str]]=None, - data: Any=None, - json: Any=None, - headers: LooseHeaders=None, - skip_auto_headers: Optional[Iterable[str]]=None, - auth: Optional[BasicAuth]=None, - allow_redirects: bool=True, - max_redirects: int=10, - compress: Optional[str]=None, - chunked: Optional[bool]=None, - expect100: bool=False, - raise_for_status: Optional[bool]=None, - read_until_eof: bool=True, - proxy: Optional[StrOrURL]=None, - proxy_auth: Optional[BasicAuth]=None, - timeout: Union[ClientTimeout, object]=sentinel, - cookies: Optional[LooseCookies]=None, - version: HttpVersion=http.HttpVersion11, - connector: Optional[BaseConnector]=None, - loop: Optional[asyncio.AbstractEventLoop]=None -) -> _SessionRequestContextManager: + if PY_35: + def __await__(self): + try: + return (yield from self._coro) + except: + yield from self._session.close() + raise + + def __del__(self): + self._session.detach() + + +class _DetachedWSRequestContextManager(_WSRequestContextManager): + + __slots__ = _WSRequestContextManager.__slots__ + ('_session', ) + + def __init__(self, coro, session): + super().__init__(coro) + self._session = session + + def __del__(self): + self._session.detach() + + +def request(method, url, *, + params=None, + data=None, + headers=None, + skip_auto_headers=None, + cookies=None, + auth=None, + allow_redirects=True, + max_redirects=10, + encoding='utf-8', + version=None, + compress=None, + chunked=None, + expect100=False, + connector=None, + loop=None, + read_until_eof=True, + request_class=None, + response_class=None, + proxy=None, + proxy_auth=None): """Constructs and sends a request. Returns response object. + method - HTTP method url - request url params - (optional) Dictionary or bytes to be sent in the query string of the new request data - (optional) Dictionary, bytes, or file-like object to send in the body of the request - json - (optional) Any json compatible python object headers - (optional) Dictionary of HTTP Headers to send with the request cookies - (optional) Dict object to send with the request @@ -1112,40 +676,111 @@ def request( connection pooling. read_until_eof - Read response until eof if response does not have Content-Length header. + request_class - (optional) Custom Request class implementation. + response_class - (optional) Custom Response class implementation. loop - Optional event loop. - timeout - Optional ClientTimeout settings structure, 5min - total timeout by default. + Usage:: + >>> import aiohttp - >>> resp = await aiohttp.request('GET', 'http://python.org/') + >>> resp = yield from aiohttp.request('GET', 'http://python.org/') >>> resp - >>> data = await resp.read() + >>> data = yield from resp.read() + """ - connector_owner = False + warnings.warn("Use ClientSession().request() instead", DeprecationWarning) if connector is None: - connector_owner = True - connector = TCPConnector(loop=loop, force_close=True) + connector = aiohttp.TCPConnector(loop=loop, force_close=True) - session = ClientSession( - loop=loop, cookies=cookies, version=version, timeout=timeout, - connector=connector, connector_owner=connector_owner) + kwargs = {} - return _SessionRequestContextManager( + if request_class is not None: + kwargs['request_class'] = request_class + + if response_class is not None: + kwargs['response_class'] = response_class + + session = ClientSession(loop=loop, + cookies=cookies, + connector=connector, + **kwargs) + return _DetachedRequestContextManager( session._request(method, url, params=params, data=data, - json=json, headers=headers, skip_auto_headers=skip_auto_headers, auth=auth, allow_redirects=allow_redirects, max_redirects=max_redirects, + encoding=encoding, + version=version, compress=compress, chunked=chunked, expect100=expect100, - raise_for_status=raise_for_status, read_until_eof=read_until_eof, proxy=proxy, proxy_auth=proxy_auth,), - session) + session=session) + + +def get(url, **kwargs): + warnings.warn("Use ClientSession().get() instead", DeprecationWarning) + return request(hdrs.METH_GET, url, **kwargs) + + +def options(url, **kwargs): + warnings.warn("Use ClientSession().options() instead", DeprecationWarning) + return request(hdrs.METH_OPTIONS, url, **kwargs) + + +def head(url, **kwargs): + warnings.warn("Use ClientSession().head() instead", DeprecationWarning) + return request(hdrs.METH_HEAD, url, **kwargs) + + +def post(url, **kwargs): + warnings.warn("Use ClientSession().post() instead", DeprecationWarning) + return request(hdrs.METH_POST, url, **kwargs) + + +def put(url, **kwargs): + warnings.warn("Use ClientSession().put() instead", DeprecationWarning) + return request(hdrs.METH_PUT, url, **kwargs) + + +def patch(url, **kwargs): + warnings.warn("Use ClientSession().patch() instead", DeprecationWarning) + return request(hdrs.METH_PATCH, url, **kwargs) + + +def delete(url, **kwargs): + warnings.warn("Use ClientSession().delete() instead", DeprecationWarning) + return request(hdrs.METH_DELETE, url, **kwargs) + + +def ws_connect(url, *, protocols=(), timeout=10.0, connector=None, auth=None, + ws_response_class=ClientWebSocketResponse, autoclose=True, + autoping=True, loop=None, origin=None, headers=None): + + warnings.warn("Use ClientSession().ws_connect() instead", + DeprecationWarning) + if loop is None: + loop = asyncio.get_event_loop() + + if connector is None: + connector = aiohttp.TCPConnector(loop=loop, force_close=True) + + session = aiohttp.ClientSession(loop=loop, connector=connector, auth=auth, + ws_response_class=ws_response_class, + headers=headers) + + return _DetachedWSRequestContextManager( + session._ws_connect(url, + protocols=protocols, + timeout=timeout, + autoclose=autoclose, + autoping=autoping, + origin=origin), + session=session) diff --git a/venv/Lib/site-packages/aiohttp/client_exceptions.py b/venv/Lib/site-packages/aiohttp/client_exceptions.py deleted file mode 100644 index a524f68e..00000000 --- a/venv/Lib/site-packages/aiohttp/client_exceptions.py +++ /dev/null @@ -1,292 +0,0 @@ -"""HTTP related errors.""" - -import asyncio -import warnings -from typing import TYPE_CHECKING, Any, Optional, Tuple, Union - -from .typedefs import _CIMultiDict - -try: - import ssl - SSLContext = ssl.SSLContext -except ImportError: # pragma: no cover - ssl = SSLContext = None # type: ignore - - -if TYPE_CHECKING: # pragma: no cover - from .client_reqrep import (RequestInfo, ClientResponse, ConnectionKey, # noqa - Fingerprint) -else: - RequestInfo = ClientResponse = ConnectionKey = None - - -__all__ = ( - 'ClientError', - - 'ClientConnectionError', - 'ClientOSError', 'ClientConnectorError', 'ClientProxyConnectionError', - - 'ClientSSLError', - 'ClientConnectorSSLError', 'ClientConnectorCertificateError', - - 'ServerConnectionError', 'ServerTimeoutError', 'ServerDisconnectedError', - 'ServerFingerprintMismatch', - - 'ClientResponseError', 'ClientHttpProxyError', - 'WSServerHandshakeError', 'ContentTypeError', - - 'ClientPayloadError', 'InvalidURL') - - -class ClientError(Exception): - """Base class for client connection errors.""" - - -class ClientResponseError(ClientError): - """Connection error during reading response. - - request_info: instance of RequestInfo - """ - - def __init__(self, request_info: RequestInfo, - history: Tuple[ClientResponse, ...], *, - code: Optional[int]=None, - status: Optional[int]=None, - message: str='', - headers: Optional[_CIMultiDict]=None) -> None: - self.request_info = request_info - if code is not None: - if status is not None: - raise ValueError( - "Both code and status arguments are provided; " - "code is deprecated, use status instead") - warnings.warn("code argument is deprecated, use status instead", - DeprecationWarning, - stacklevel=2) - if status is not None: - self.status = status - elif code is not None: - self.status = code - else: - self.status = 0 - self.message = message - self.headers = headers - self.history = history - self.args = (request_info, history) - - def __str__(self) -> str: - return ("%s, message=%r, url=%r" % - (self.status, self.message, self.request_info.real_url)) - - def __repr__(self) -> str: - args = "%r, %r" % (self.request_info, self.history) - if self.status != 0: - args += ", status=%r" % (self.status,) - if self.message != '': - args += ", message=%r" % (self.message,) - if self.headers is not None: - args += ", headers=%r" % (self.headers,) - return "%s(%s)" % (type(self).__name__, args) - - @property - def code(self) -> int: - warnings.warn("code property is deprecated, use status instead", - DeprecationWarning, - stacklevel=2) - return self.status - - @code.setter - def code(self, value: int) -> None: - warnings.warn("code property is deprecated, use status instead", - DeprecationWarning, - stacklevel=2) - self.status = value - - -class ContentTypeError(ClientResponseError): - """ContentType found is not valid.""" - - -class WSServerHandshakeError(ClientResponseError): - """websocket server handshake error.""" - - -class ClientHttpProxyError(ClientResponseError): - """HTTP proxy error. - - Raised in :class:`aiohttp.connector.TCPConnector` if - proxy responds with status other than ``200 OK`` - on ``CONNECT`` request. - """ - - -class TooManyRedirects(ClientResponseError): - """Client was redirected too many times.""" - - -class ClientConnectionError(ClientError): - """Base class for client socket errors.""" - - -class ClientOSError(ClientConnectionError, OSError): - """OSError error.""" - - -class ClientConnectorError(ClientOSError): - """Client connector error. - - Raised in :class:`aiohttp.connector.TCPConnector` if - connection to proxy can not be established. - """ - def __init__(self, connection_key: ConnectionKey, - os_error: OSError) -> None: - self._conn_key = connection_key - self._os_error = os_error - super().__init__(os_error.errno, os_error.strerror) - self.args = (connection_key, os_error) - - @property - def os_error(self) -> OSError: - return self._os_error - - @property - def host(self) -> str: - return self._conn_key.host - - @property - def port(self) -> Optional[int]: - return self._conn_key.port - - @property - def ssl(self) -> Union[SSLContext, None, bool, 'Fingerprint']: - return self._conn_key.ssl - - def __str__(self) -> str: - return ('Cannot connect to host {0.host}:{0.port} ssl:{1} [{2}]' - .format(self, self.ssl if self.ssl is not None else 'default', - self.strerror)) - - # OSError.__reduce__ does too much black magick - __reduce__ = BaseException.__reduce__ - - -class ClientProxyConnectionError(ClientConnectorError): - """Proxy connection error. - - Raised in :class:`aiohttp.connector.TCPConnector` if - connection to proxy can not be established. - """ - - -class ServerConnectionError(ClientConnectionError): - """Server connection errors.""" - - -class ServerDisconnectedError(ServerConnectionError): - """Server disconnected.""" - - def __init__(self, message: Optional[str]=None) -> None: - self.message = message - if message is None: - self.args = () - else: - self.args = (message,) - - -class ServerTimeoutError(ServerConnectionError, asyncio.TimeoutError): - """Server timeout error.""" - - -class ServerFingerprintMismatch(ServerConnectionError): - """SSL certificate does not match expected fingerprint.""" - - def __init__(self, expected: bytes, got: bytes, - host: str, port: int) -> None: - self.expected = expected - self.got = got - self.host = host - self.port = port - self.args = (expected, got, host, port) - - def __repr__(self) -> str: - return '<{} expected={!r} got={!r} host={!r} port={!r}>'.format( - self.__class__.__name__, self.expected, self.got, - self.host, self.port) - - -class ClientPayloadError(ClientError): - """Response payload error.""" - - -class InvalidURL(ClientError, ValueError): - """Invalid URL. - - URL used for fetching is malformed, e.g. it doesn't contains host - part.""" - - # Derive from ValueError for backward compatibility - - def __init__(self, url: Any) -> None: - # The type of url is not yarl.URL because the exception can be raised - # on URL(url) call - super().__init__(url) - - @property - def url(self) -> Any: - return self.args[0] - - def __repr__(self) -> str: - return '<{} {}>'.format(self.__class__.__name__, self.url) - - -class ClientSSLError(ClientConnectorError): - """Base error for ssl.*Errors.""" - - -if ssl is not None: - cert_errors = (ssl.CertificateError,) - cert_errors_bases = (ClientSSLError, ssl.CertificateError,) - - ssl_errors = (ssl.SSLError,) - ssl_error_bases = (ClientSSLError, ssl.SSLError) -else: # pragma: no cover - cert_errors = tuple() - cert_errors_bases = (ClientSSLError, ValueError,) - - ssl_errors = tuple() - ssl_error_bases = (ClientSSLError,) - - -class ClientConnectorSSLError(*ssl_error_bases): # type: ignore - """Response ssl error.""" - - -class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore - """Response certificate error.""" - - def __init__(self, connection_key: - ConnectionKey, certificate_error: Exception) -> None: - self._conn_key = connection_key - self._certificate_error = certificate_error - self.args = (connection_key, certificate_error) - - @property - def certificate_error(self) -> Exception: - return self._certificate_error - - @property - def host(self) -> str: - return self._conn_key.host - - @property - def port(self) -> Optional[int]: - return self._conn_key.port - - @property - def ssl(self) -> bool: - return self._conn_key.is_ssl - - def __str__(self) -> str: - return ('Cannot connect to host {0.host}:{0.port} ssl:{0.ssl} ' - '[{0.certificate_error.__class__.__name__}: ' - '{0.certificate_error.args}]'.format(self)) diff --git a/venv/Lib/site-packages/aiohttp/client_proto.py b/venv/Lib/site-packages/aiohttp/client_proto.py deleted file mode 100644 index a44e6454..00000000 --- a/venv/Lib/site-packages/aiohttp/client_proto.py +++ /dev/null @@ -1,239 +0,0 @@ -import asyncio -from contextlib import suppress -from typing import Any, Optional, Tuple - -from .base_protocol import BaseProtocol -from .client_exceptions import ( - ClientOSError, - ClientPayloadError, - ServerDisconnectedError, - ServerTimeoutError, -) -from .helpers import BaseTimerContext -from .http import HttpResponseParser, RawResponseMessage -from .streams import EMPTY_PAYLOAD, DataQueue, StreamReader - - -class ResponseHandler(BaseProtocol, - DataQueue[Tuple[RawResponseMessage, StreamReader]]): - """Helper class to adapt between Protocol and StreamReader.""" - - def __init__(self, - loop: asyncio.AbstractEventLoop) -> None: - BaseProtocol.__init__(self, loop=loop) - DataQueue.__init__(self, loop) - - self._should_close = False - - self._payload = None - self._skip_payload = False - self._payload_parser = None - - self._timer = None - - self._tail = b'' - self._upgraded = False - self._parser = None # type: Optional[HttpResponseParser] - - self._read_timeout = None # type: Optional[float] - self._read_timeout_handle = None # type: Optional[asyncio.TimerHandle] - - @property - def upgraded(self) -> bool: - return self._upgraded - - @property - def should_close(self) -> bool: - if (self._payload is not None and - not self._payload.is_eof() or self._upgraded): - return True - - return (self._should_close or self._upgraded or - self.exception() is not None or - self._payload_parser is not None or - len(self) > 0 or bool(self._tail)) - - def force_close(self) -> None: - self._should_close = True - - def close(self) -> None: - transport = self.transport - if transport is not None: - transport.close() - self.transport = None - self._payload = None - self._drop_timeout() - - def is_connected(self) -> bool: - return self.transport is not None - - def connection_lost(self, exc: Optional[BaseException]) -> None: - self._drop_timeout() - - if self._payload_parser is not None: - with suppress(Exception): - self._payload_parser.feed_eof() - - uncompleted = None - if self._parser is not None: - try: - uncompleted = self._parser.feed_eof() - except Exception: - if self._payload is not None: - self._payload.set_exception( - ClientPayloadError( - 'Response payload is not completed')) - - if not self.is_eof(): - if isinstance(exc, OSError): - exc = ClientOSError(*exc.args) - if exc is None: - exc = ServerDisconnectedError(uncompleted) - # assigns self._should_close to True as side effect, - # we do it anyway below - self.set_exception(exc) - - self._should_close = True - self._parser = None - self._payload = None - self._payload_parser = None - self._reading_paused = False - - super().connection_lost(exc) - - def eof_received(self) -> None: - # should call parser.feed_eof() most likely - self._drop_timeout() - - def pause_reading(self) -> None: - super().pause_reading() - self._drop_timeout() - - def resume_reading(self) -> None: - super().resume_reading() - self._reschedule_timeout() - - def set_exception(self, exc: BaseException) -> None: - self._should_close = True - self._drop_timeout() - super().set_exception(exc) - - def set_parser(self, parser: Any, payload: Any) -> None: - # TODO: actual types are: - # parser: WebSocketReader - # payload: FlowControlDataQueue - # but they are not generi enough - # Need an ABC for both types - self._payload = payload - self._payload_parser = parser - - self._drop_timeout() - - if self._tail: - data, self._tail = self._tail, b'' - self.data_received(data) - - def set_response_params(self, *, timer: BaseTimerContext=None, - skip_payload: bool=False, - read_until_eof: bool=False, - auto_decompress: bool=True, - read_timeout: Optional[float]=None) -> None: - self._skip_payload = skip_payload - - self._read_timeout = read_timeout - self._reschedule_timeout() - - self._parser = HttpResponseParser( - self, self._loop, timer=timer, - payload_exception=ClientPayloadError, - read_until_eof=read_until_eof, - auto_decompress=auto_decompress) - - if self._tail: - data, self._tail = self._tail, b'' - self.data_received(data) - - def _drop_timeout(self) -> None: - if self._read_timeout_handle is not None: - self._read_timeout_handle.cancel() - self._read_timeout_handle = None - - def _reschedule_timeout(self) -> None: - timeout = self._read_timeout - if self._read_timeout_handle is not None: - self._read_timeout_handle.cancel() - - if timeout: - self._read_timeout_handle = self._loop.call_later( - timeout, self._on_read_timeout) - else: - self._read_timeout_handle = None - - def _on_read_timeout(self) -> None: - exc = ServerTimeoutError("Timeout on reading data from socket") - self.set_exception(exc) - if self._payload is not None: - self._payload.set_exception(exc) - - def data_received(self, data: bytes) -> None: - self._reschedule_timeout() - - if not data: - return - - # custom payload parser - if self._payload_parser is not None: - eof, tail = self._payload_parser.feed_data(data) - if eof: - self._payload = None - self._payload_parser = None - - if tail: - self.data_received(tail) - return - else: - if self._upgraded or self._parser is None: - # i.e. websocket connection, websocket parser is not set yet - self._tail += data - else: - # parse http messages - try: - messages, upgraded, tail = self._parser.feed_data(data) - except BaseException as exc: - if self.transport is not None: - # connection.release() could be called BEFORE - # data_received(), the transport is already - # closed in this case - self.transport.close() - # should_close is True after the call - self.set_exception(exc) - return - - self._upgraded = upgraded - - payload = None - for message, payload in messages: - if message.should_close: - self._should_close = True - - self._payload = payload - - if self._skip_payload or message.code in (204, 304): - self.feed_data((message, EMPTY_PAYLOAD), 0) # type: ignore # noqa - else: - self.feed_data((message, payload), 0) - if payload is not None: - # new message(s) was processed - # register timeout handler unsubscribing - # either on end-of-stream or immediately for - # EMPTY_PAYLOAD - if payload is not EMPTY_PAYLOAD: - payload.on_eof(self._drop_timeout) - else: - self._drop_timeout() - - if tail: - if upgraded: - self.data_received(tail) - else: - self._tail = tail diff --git a/venv/Lib/site-packages/aiohttp/client_reqrep.py b/venv/Lib/site-packages/aiohttp/client_reqrep.py index 1d645097..86310074 100644 --- a/venv/Lib/site-packages/aiohttp/client_reqrep.py +++ b/venv/Lib/site-packages/aiohttp/client_reqrep.py @@ -1,225 +1,58 @@ import asyncio -import codecs +import collections +import http.cookies import io -import re +import json +import mimetypes +import os import sys import traceback +import urllib.parse import warnings -from hashlib import md5, sha1, sha256 -from http.cookies import CookieError, Morsel, SimpleCookie -from types import MappingProxyType, TracebackType -from typing import ( # noqa - TYPE_CHECKING, - Any, - Dict, - Iterable, - List, - Mapping, - Optional, - Tuple, - Type, - Union, - cast, -) - -import attr + from multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy -from yarl import URL - -from . import hdrs, helpers, http, multipart, payload -from .abc import AbstractStreamWriter -from .client_exceptions import ( - ClientConnectionError, - ClientOSError, - ClientResponseError, - ContentTypeError, - InvalidURL, - ServerFingerprintMismatch, -) -from .formdata import FormData -from .helpers import ( # noqa - PY_36, - BaseTimerContext, - BasicAuth, - HeadersMixin, - TimerNoop, - noop, - reify, - set_result, -) -from .http import SERVER_SOFTWARE, HttpVersion10, HttpVersion11, StreamWriter -from .log import client_logger -from .streams import StreamReader # noqa -from .typedefs import ( - DEFAULT_JSON_DECODER, - JSONDecoder, - LooseCookies, - LooseHeaders, - RawHeaders, -) -try: - import ssl - from ssl import SSLContext -except ImportError: # pragma: no cover - ssl = None # type: ignore - SSLContext = object # type: ignore +import aiohttp + +from . import hdrs, helpers, streams +from .helpers import Timeout +from .log import client_logger +from .multipart import MultipartWriter +from .protocol import HttpMessage +from .streams import EOF_MARKER, FlowControlStreamReader try: import cchardet as chardet -except ImportError: # pragma: no cover +except ImportError: import chardet -__all__ = ('ClientRequest', 'ClientResponse', 'RequestInfo', 'Fingerprint') - - -if TYPE_CHECKING: # pragma: no cover - from .client import ClientSession # noqa - from .connector import Connection # noqa - from .tracing import Trace # noqa - - -json_re = re.compile(r'^application/(?:[\w.+-]+?\+)?json') - - -@attr.s(frozen=True, slots=True) -class ContentDisposition: - type = attr.ib(type=str) # type: Optional[str] - parameters = attr.ib(type=MappingProxyType) # type: MappingProxyType[str, str] # noqa - filename = attr.ib(type=str) # type: Optional[str] +__all__ = ('ClientRequest', 'ClientResponse') +PY_35 = sys.version_info >= (3, 5) -@attr.s(frozen=True, slots=True) -class RequestInfo: - url = attr.ib(type=URL) - method = attr.ib(type=str) - headers = attr.ib(type=CIMultiDictProxy) # type: CIMultiDictProxy[str] - real_url = attr.ib(type=URL) - - @real_url.default - def real_url_default(self) -> URL: - return self.url - - -class Fingerprint: - HASHFUNC_BY_DIGESTLEN = { - 16: md5, - 20: sha1, - 32: sha256, - } - - def __init__(self, fingerprint: bytes) -> None: - digestlen = len(fingerprint) - hashfunc = self.HASHFUNC_BY_DIGESTLEN.get(digestlen) - if not hashfunc: - raise ValueError('fingerprint has invalid length') - elif hashfunc is md5 or hashfunc is sha1: - raise ValueError('md5 and sha1 are insecure and ' - 'not supported. Use sha256.') - self._hashfunc = hashfunc - self._fingerprint = fingerprint - - @property - def fingerprint(self) -> bytes: - return self._fingerprint - - def check(self, transport: asyncio.Transport) -> None: - if not transport.get_extra_info('sslcontext'): - return - sslobj = transport.get_extra_info('ssl_object') - cert = sslobj.getpeercert(binary_form=True) - got = self._hashfunc(cert).digest() - if got != self._fingerprint: - host, port, *_ = transport.get_extra_info('peername') - raise ServerFingerprintMismatch(self._fingerprint, - got, host, port) - - -if ssl is not None: - SSL_ALLOWED_TYPES = (ssl.SSLContext, bool, Fingerprint, type(None)) -else: # pragma: no cover - SSL_ALLOWED_TYPES = type(None) - - -def _merge_ssl_params( - ssl: Union['SSLContext', bool, Fingerprint, None], - verify_ssl: Optional[bool], - ssl_context: Optional['SSLContext'], - fingerprint: Optional[bytes] -) -> Union['SSLContext', bool, Fingerprint, None]: - if verify_ssl is not None and not verify_ssl: - warnings.warn("verify_ssl is deprecated, use ssl=False instead", - DeprecationWarning, - stacklevel=3) - if ssl is not None: - raise ValueError("verify_ssl, ssl_context, fingerprint and ssl " - "parameters are mutually exclusive") - else: - ssl = False - if ssl_context is not None: - warnings.warn("ssl_context is deprecated, use ssl=context instead", - DeprecationWarning, - stacklevel=3) - if ssl is not None: - raise ValueError("verify_ssl, ssl_context, fingerprint and ssl " - "parameters are mutually exclusive") - else: - ssl = ssl_context - if fingerprint is not None: - warnings.warn("fingerprint is deprecated, " - "use ssl=Fingerprint(fingerprint) instead", - DeprecationWarning, - stacklevel=3) - if ssl is not None: - raise ValueError("verify_ssl, ssl_context, fingerprint and ssl " - "parameters are mutually exclusive") - else: - ssl = Fingerprint(fingerprint) - if not isinstance(ssl, SSL_ALLOWED_TYPES): - raise TypeError("ssl should be SSLContext, bool, Fingerprint or None, " - "got {!r} instead.".format(ssl)) - return ssl - - -@attr.s(slots=True, frozen=True) -class ConnectionKey: - # the key should contain an information about used proxy / TLS - # to prevent reusing wrong connections from a pool - host = attr.ib(type=str) - port = attr.ib(type=int) # type: Optional[int] - is_ssl = attr.ib(type=bool) - ssl = attr.ib() # type: Union[SSLContext, None, bool, Fingerprint] - proxy = attr.ib() # type: Optional[URL] - proxy_auth = attr.ib() # type: Optional[BasicAuth] - proxy_headers_hash = attr.ib(type=int) # type: Optional[int] # noqa # hash(CIMultiDict) - - -def _is_expected_content_type(response_content_type: str, - expected_content_type: str) -> bool: - if expected_content_type == 'application/json': - return json_re.match(response_content_type) is not None - return expected_content_type in response_content_type +HTTP_PORT = 80 +HTTPS_PORT = 443 class ClientRequest: - GET_METHODS = { - hdrs.METH_GET, - hdrs.METH_HEAD, - hdrs.METH_OPTIONS, - hdrs.METH_TRACE, - } + + GET_METHODS = {hdrs.METH_GET, hdrs.METH_HEAD, hdrs.METH_OPTIONS} POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT} - ALL_METHODS = GET_METHODS.union(POST_METHODS).union({hdrs.METH_DELETE}) + ALL_METHODS = GET_METHODS.union(POST_METHODS).union( + {hdrs.METH_DELETE, hdrs.METH_TRACE}) DEFAULT_HEADERS = { hdrs.ACCEPT: '*/*', hdrs.ACCEPT_ENCODING: 'gzip, deflate', } + SERVER_SOFTWARE = HttpMessage.SERVER_SOFTWARE + body = b'' auth = None response = None + response_class = None _writer = None # async task for streaming data _continue = None # waiter future for '100 Continue' response @@ -229,121 +62,99 @@ class ClientRequest: # because _writer is instance method, thus it keeps a reference to self. # Until writer has finished finalizer will not be called. - def __init__(self, method: str, url: URL, *, - params: Optional[Mapping[str, str]]=None, - headers: Optional[LooseHeaders]=None, - skip_auto_headers: Iterable[str]=frozenset(), - data: Any=None, - cookies: Optional[LooseCookies]=None, - auth: Optional[BasicAuth]=None, - version: http.HttpVersion=http.HttpVersion11, - compress: Optional[str]=None, - chunked: Optional[bool]=None, - expect100: bool=False, - loop: Optional[asyncio.AbstractEventLoop]=None, - response_class: Optional[Type['ClientResponse']]=None, - proxy: Optional[URL]=None, - proxy_auth: Optional[BasicAuth]=None, - timer: Optional[BaseTimerContext]=None, - session: Optional['ClientSession']=None, - ssl: Union[SSLContext, bool, Fingerprint, None]=None, - proxy_headers: Optional[LooseHeaders]=None, - traces: Optional[List['Trace']]=None): + def __init__(self, method, url, *, + params=None, headers=None, skip_auto_headers=frozenset(), + data=None, cookies=None, + auth=None, encoding='utf-8', + version=aiohttp.HttpVersion11, compress=None, + chunked=None, expect100=False, + loop=None, response_class=None, + proxy=None, proxy_auth=None, + timeout=5*60): if loop is None: loop = asyncio.get_event_loop() - assert isinstance(url, URL), url - assert isinstance(proxy, (URL, type(None))), proxy - # FIXME: session is None in tests only, need to fix tests - # assert session is not None - self._session = cast('ClientSession', session) - if params: - q = MultiDict(url.query) - url2 = url.with_query(params) - q.extend(url2.query) - url = url.with_query(q) - self.original_url = url - self.url = url.with_fragment(None) + self.url = url self.method = method.upper() + self.encoding = encoding self.chunked = chunked self.compress = compress self.loop = loop - self.length = None - if response_class is None: - real_response_class = ClientResponse - else: - real_response_class = response_class - self.response_class = real_response_class # type: Type[ClientResponse] - self._timer = timer if timer is not None else TimerNoop() - self._ssl = ssl + self.response_class = response_class or ClientResponse + self._timeout = timeout if loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1)) self.update_version(version) self.update_host(url) + self.update_path(params) self.update_headers(headers) self.update_auto_headers(skip_auto_headers) self.update_cookies(cookies) self.update_content_encoding(data) self.update_auth(auth) - self.update_proxy(proxy, proxy_auth, proxy_headers) + self.update_proxy(proxy, proxy_auth) - self.update_body_from_data(data) - if data or self.method not in self.GET_METHODS: - self.update_transfer_encoding() + self.update_body_from_data(data, skip_auto_headers) + self.update_transfer_encoding() self.update_expect_continue(expect100) - if traces is None: - traces = [] - self._traces = traces - - def is_ssl(self) -> bool: - return self.url.scheme in ('https', 'wss') - @property - def ssl(self) -> Union['SSLContext', None, bool, Fingerprint]: - return self._ssl - - @property - def connection_key(self) -> ConnectionKey: - proxy_headers = self.proxy_headers - if proxy_headers: - h = hash(tuple((k, v) for k, v in proxy_headers.items())) # type: Optional[int] # noqa - else: - h = None - return ConnectionKey(self.host, self.port, self.is_ssl(), - self.ssl, - self.proxy, self.proxy_auth, h) + def update_host(self, url): + """Update destination host, port and connection type (ssl).""" + url_parsed = urllib.parse.urlsplit(url) - @property - def host(self) -> str: - ret = self.url.host - assert ret is not None - return ret + # check for network location part + netloc = url_parsed.netloc + if not netloc: + raise ValueError('Host could not be detected.') - @property - def port(self) -> Optional[int]: - return self.url.port + # get host/port + host = url_parsed.hostname + if not host: + raise ValueError('Host could not be detected.') - @property - def request_info(self) -> RequestInfo: - headers = CIMultiDictProxy(self.headers) # type: CIMultiDictProxy[str] - return RequestInfo(self.url, self.method, - headers, self.original_url) + try: + port = url_parsed.port + except ValueError: + raise ValueError( + 'Port number could not be converted.') from None - def update_host(self, url: URL) -> None: - """Update destination host, port and connection type (ssl).""" - # get host/port - if not url.host: - raise InvalidURL(url) + # check domain idna encoding + try: + host = host.encode('idna').decode('utf-8') + netloc = self.make_netloc(host, url_parsed.port) + except UnicodeError: + raise ValueError('URL has an invalid label.') # basic auth info - username, password = url.user, url.password + username, password = url_parsed.username, url_parsed.password if username: self.auth = helpers.BasicAuth(username, password or '') - def update_version(self, version: Union[http.HttpVersion, str]) -> None: + # Record entire netloc for usage in host header + self.netloc = netloc + + scheme = url_parsed.scheme + self.ssl = scheme in ('https', 'wss') + + # set port number if it isn't already set + if not port: + if self.ssl: + port = HTTPS_PORT + else: + port = HTTP_PORT + + self.host, self.port, self.scheme = host, port, scheme + + def make_netloc(self, host, port): + ret = host + if port: + ret = ret + ':' + str(port) + return ret + + def update_version(self, version): """Convert request version to two elements tuple. parser HTTP version '1.1' => (1, 1) @@ -351,113 +162,102 @@ class ClientRequest: if isinstance(version, str): v = [l.strip() for l in version.split('.', 1)] try: - version = http.HttpVersion(int(v[0]), int(v[1])) + version = int(v[0]), int(v[1]) except ValueError: raise ValueError( 'Can not parse http version number: {}' .format(version)) from None self.version = version - def update_headers(self, headers: Optional[LooseHeaders]) -> None: - """Update request headers.""" - self.headers = CIMultiDict() # type: CIMultiDict[str] + def update_path(self, params): + """Build path.""" + # extract path + scheme, netloc, path, query, fragment = urllib.parse.urlsplit(self.url) + if not path: + path = '/' - # add host - netloc = cast(str, self.url.raw_host) - if helpers.is_ipv6_address(netloc): - netloc = '[{}]'.format(netloc) - if self.url.port is not None and not self.url.is_default_port(): - netloc += ':' + str(self.url.port) - self.headers[hdrs.HOST] = netloc + if isinstance(params, collections.Mapping): + params = list(params.items()) + + if params: + if not isinstance(params, str): + params = urllib.parse.urlencode(params) + if query: + query = '%s&%s' % (query, params) + else: + query = params + self.path = urllib.parse.urlunsplit(('', '', helpers.requote_uri(path), + query, '')) + self.url = urllib.parse.urlunsplit( + (scheme, netloc, self.path, '', fragment)) + + def update_headers(self, headers): + """Update request headers.""" + self.headers = CIMultiDict() if headers: - if isinstance(headers, (dict, MultiDictProxy, MultiDict)): - headers = headers.items() # type: ignore + if isinstance(headers, dict): + headers = headers.items() + elif isinstance(headers, (MultiDictProxy, MultiDict)): + headers = headers.items() for key, value in headers: - # A special case for Host header - if key.lower() == 'host': - self.headers[key] = value - else: - self.headers.add(key, value) - - def update_auto_headers(self, skip_auto_headers: Iterable[str]) -> None: - self.skip_auto_headers = CIMultiDict( - (hdr, None) for hdr in sorted(skip_auto_headers)) - used_headers = self.headers.copy() - used_headers.extend(self.skip_auto_headers) # type: ignore + self.headers.add(key, value) + + def update_auto_headers(self, skip_auto_headers): + self.skip_auto_headers = skip_auto_headers + used_headers = set(self.headers) | skip_auto_headers for hdr, val in self.DEFAULT_HEADERS.items(): if hdr not in used_headers: self.headers.add(hdr, val) + # add host + if hdrs.HOST not in used_headers: + self.headers[hdrs.HOST] = self.netloc + if hdrs.USER_AGENT not in used_headers: - self.headers[hdrs.USER_AGENT] = SERVER_SOFTWARE + self.headers[hdrs.USER_AGENT] = self.SERVER_SOFTWARE - def update_cookies(self, cookies: Optional[LooseCookies]) -> None: + def update_cookies(self, cookies): """Update request cookies header.""" if not cookies: return - c = SimpleCookie() + c = http.cookies.SimpleCookie() if hdrs.COOKIE in self.headers: c.load(self.headers.get(hdrs.COOKIE, '')) del self.headers[hdrs.COOKIE] - if isinstance(cookies, Mapping): - iter_cookies = cookies.items() - else: - iter_cookies = cookies # type: ignore - for name, value in iter_cookies: - if isinstance(value, Morsel): - # Preserve coded_value - mrsl_val = value.get(value.key, Morsel()) - mrsl_val.set(value.key, value.value, value.coded_value) - c[name] = mrsl_val + if isinstance(cookies, dict): + cookies = cookies.items() + + for name, value in cookies: + if isinstance(value, http.cookies.Morsel): + c[value.key] = value.value else: - c[name] = value # type: ignore + c[name] = value self.headers[hdrs.COOKIE] = c.output(header='', sep=';').strip() - def update_content_encoding(self, data: Any) -> None: + def update_content_encoding(self, data): """Set request content encoding.""" if not data: return enc = self.headers.get(hdrs.CONTENT_ENCODING, '').lower() if enc: - if self.compress: - raise ValueError( - 'compress can not be set ' - 'if Content-Encoding header is set') + if self.compress is not False: + self.compress = enc + # enable chunked, no need to deal with length + self.chunked = True elif self.compress: if not isinstance(self.compress, str): self.compress = 'deflate' self.headers[hdrs.CONTENT_ENCODING] = self.compress self.chunked = True # enable chunked, no need to deal with length - def update_transfer_encoding(self) -> None: - """Analyze transfer-encoding header.""" - te = self.headers.get(hdrs.TRANSFER_ENCODING, '').lower() - - if 'chunked' in te: - if self.chunked: - raise ValueError( - 'chunked can not be set ' - 'if "Transfer-Encoding: chunked" header is set') - - elif self.chunked: - if hdrs.CONTENT_LENGTH in self.headers: - raise ValueError( - 'chunked can not be set ' - 'if Content-Length header is set') - - self.headers[hdrs.TRANSFER_ENCODING] = 'chunked' - else: - if hdrs.CONTENT_LENGTH not in self.headers: - self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body)) - - def update_auth(self, auth: Optional[BasicAuth]) -> None: + def update_auth(self, auth): """Set basic auth.""" if auth is None: auth = self.auth @@ -469,140 +269,233 @@ class ClientRequest: self.headers[hdrs.AUTHORIZATION] = auth.encode() - def update_body_from_data(self, body: Any) -> None: - if not body: + def update_body_from_data(self, data, skip_auto_headers): + if not data: return - # FormData - if isinstance(body, FormData): - body = body() - - try: - body = payload.PAYLOAD_REGISTRY.get(body, disposition=None) - except payload.LookupError: - body = FormData(body)() + if isinstance(data, str): + data = data.encode(self.encoding) - self.body = body + if isinstance(data, (bytes, bytearray)): + self.body = data + if (hdrs.CONTENT_TYPE not in self.headers and + hdrs.CONTENT_TYPE not in skip_auto_headers): + self.headers[hdrs.CONTENT_TYPE] = 'application/octet-stream' + if hdrs.CONTENT_LENGTH not in self.headers and not self.chunked: + self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body)) - # enable chunked encoding if needed - if not self.chunked: - if hdrs.CONTENT_LENGTH not in self.headers: - size = body.size - if size is None: + elif isinstance(data, (asyncio.StreamReader, streams.StreamReader, + streams.DataQueue)): + self.body = data + + elif asyncio.iscoroutine(data): + self.body = data + if (hdrs.CONTENT_LENGTH not in self.headers and + self.chunked is None): + self.chunked = True + + elif isinstance(data, io.IOBase): + assert not isinstance(data, io.StringIO), \ + 'attempt to send text data instead of binary' + self.body = data + if not self.chunked and isinstance(data, io.BytesIO): + # Not chunking if content-length can be determined + size = len(data.getbuffer()) + self.headers[hdrs.CONTENT_LENGTH] = str(size) + self.chunked = False + elif not self.chunked and isinstance(data, io.BufferedReader): + # Not chunking if content-length can be determined + try: + size = os.fstat(data.fileno()).st_size - data.tell() + self.headers[hdrs.CONTENT_LENGTH] = str(size) + self.chunked = False + except OSError: + # data.fileno() is not supported, e.g. + # io.BufferedReader(io.BytesIO(b'data')) self.chunked = True - else: - if hdrs.CONTENT_LENGTH not in self.headers: - self.headers[hdrs.CONTENT_LENGTH] = str(size) - - # copy payload headers - assert body.headers - for (key, value) in body.headers.items(): - if key in self.headers: - continue - if key in self.skip_auto_headers: - continue - self.headers[key] = value - - def update_expect_continue(self, expect: bool=False) -> None: + else: + self.chunked = True + + if hasattr(data, 'mode'): + if data.mode == 'r': + raise ValueError('file {!r} should be open in binary mode' + ''.format(data)) + if (hdrs.CONTENT_TYPE not in self.headers and + hdrs.CONTENT_TYPE not in skip_auto_headers and + hasattr(data, 'name')): + mime = mimetypes.guess_type(data.name)[0] + mime = 'application/octet-stream' if mime is None else mime + self.headers[hdrs.CONTENT_TYPE] = mime + + elif isinstance(data, MultipartWriter): + self.body = data.serialize() + self.headers.update(data.headers) + self.chunked = self.chunked or 8192 + + else: + if not isinstance(data, helpers.FormData): + data = helpers.FormData(data) + + self.body = data(self.encoding) + + if (hdrs.CONTENT_TYPE not in self.headers and + hdrs.CONTENT_TYPE not in skip_auto_headers): + self.headers[hdrs.CONTENT_TYPE] = data.content_type + + if data.is_multipart: + self.chunked = self.chunked or 8192 + else: + if (hdrs.CONTENT_LENGTH not in self.headers and + not self.chunked): + self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body)) + + def update_transfer_encoding(self): + """Analyze transfer-encoding header.""" + te = self.headers.get(hdrs.TRANSFER_ENCODING, '').lower() + + if self.chunked: + if hdrs.CONTENT_LENGTH in self.headers: + del self.headers[hdrs.CONTENT_LENGTH] + if 'chunked' not in te: + self.headers[hdrs.TRANSFER_ENCODING] = 'chunked' + + self.chunked = self.chunked if type(self.chunked) is int else 8192 + else: + if 'chunked' in te: + self.chunked = 8192 + else: + self.chunked = None + if hdrs.CONTENT_LENGTH not in self.headers: + self.headers[hdrs.CONTENT_LENGTH] = str(len(self.body)) + + def update_expect_continue(self, expect=False): if expect: self.headers[hdrs.EXPECT] = '100-continue' elif self.headers.get(hdrs.EXPECT, '').lower() == '100-continue': expect = True if expect: - self._continue = self.loop.create_future() + self._continue = helpers.create_future(self.loop) - def update_proxy(self, proxy: Optional[URL], - proxy_auth: Optional[BasicAuth], - proxy_headers: Optional[LooseHeaders]) -> None: - if proxy and not proxy.scheme == 'http': + def update_proxy(self, proxy, proxy_auth): + if proxy and not proxy.startswith('http://'): raise ValueError("Only http proxies are supported") if proxy_auth and not isinstance(proxy_auth, helpers.BasicAuth): raise ValueError("proxy_auth must be None or BasicAuth() tuple") self.proxy = proxy self.proxy_auth = proxy_auth - self.proxy_headers = proxy_headers - - def keep_alive(self) -> bool: - if self.version < HttpVersion10: - # keep alive not supported at all - return False - if self.version == HttpVersion10: - if self.headers.get(hdrs.CONNECTION) == 'keep-alive': - return True - else: # no headers means we close for Http 1.0 - return False - elif self.headers.get(hdrs.CONNECTION) == 'close': - return False - - return True - - async def write_bytes(self, writer: AbstractStreamWriter, - conn: 'Connection') -> None: + + @asyncio.coroutine + def write_bytes(self, request, reader): """Support coroutines that yields bytes objects.""" # 100 response if self._continue is not None: - await writer.drain() - await self._continue + yield from self._continue - protocol = conn.protocol - assert protocol is not None try: - if isinstance(self.body, payload.Payload): - await self.body.write(writer) + if asyncio.iscoroutine(self.body): + request.transport.set_tcp_nodelay(True) + exc = None + value = None + stream = self.body + + while True: + try: + if exc is not None: + result = stream.throw(exc) + else: + result = stream.send(value) + except StopIteration as exc: + if isinstance(exc.value, bytes): + yield from request.write(exc.value, drain=True) + break + except: + self.response.close() + raise + + if isinstance(result, asyncio.Future): + exc = None + value = None + try: + value = yield result + except Exception as err: + exc = err + elif isinstance(result, (bytes, bytearray)): + yield from request.write(result, drain=True) + value = None + else: + raise ValueError( + 'Bytes object is expected, got: %s.' % + type(result)) + + elif isinstance(self.body, (asyncio.StreamReader, + streams.StreamReader)): + request.transport.set_tcp_nodelay(True) + chunk = yield from self.body.read(streams.DEFAULT_LIMIT) + while chunk: + yield from request.write(chunk, drain=True) + chunk = yield from self.body.read(streams.DEFAULT_LIMIT) + + elif isinstance(self.body, streams.DataQueue): + request.transport.set_tcp_nodelay(True) + while True: + try: + chunk = yield from self.body.read() + if chunk is EOF_MARKER: + break + yield from request.write(chunk, drain=True) + except streams.EofStream: + break + + elif isinstance(self.body, io.IOBase): + chunk = self.body.read(self.chunked) + while chunk: + request.write(chunk) + chunk = self.body.read(self.chunked) + request.transport.set_tcp_nodelay(True) + else: if isinstance(self.body, (bytes, bytearray)): - self.body = (self.body,) # type: ignore + self.body = (self.body,) for chunk in self.body: - await writer.write(chunk) # type: ignore + request.write(chunk) + request.transport.set_tcp_nodelay(True) - await writer.write_eof() - except OSError as exc: - new_exc = ClientOSError( - exc.errno, + except Exception as exc: + new_exc = aiohttp.ClientRequestError( 'Can not write request body for %s' % self.url) new_exc.__context__ = exc new_exc.__cause__ = exc - protocol.set_exception(new_exc) - except asyncio.CancelledError as exc: - if not conn.closed: - protocol.set_exception(exc) - except Exception as exc: - protocol.set_exception(exc) - finally: - self._writer = None - - async def send(self, conn: 'Connection') -> 'ClientResponse': - # Specify request target: - # - CONNECT request must send authority form URI - # - not CONNECT proxy must send absolute form URI - # - most common is origin form URI - if self.method == hdrs.METH_CONNECT: - connect_host = self.url.raw_host - assert connect_host is not None - if helpers.is_ipv6_address(connect_host): - connect_host = '[{}]'.format(connect_host) - path = '{}:{}'.format(connect_host, self.url.port) - elif self.proxy and not self.is_ssl(): - path = str(self.url) + reader.set_exception(new_exc) else: - path = self.url.raw_path - if self.url.raw_query_string: - path += '?' + self.url.raw_query_string + assert request.transport.tcp_nodelay + try: + ret = request.write_eof() + # NB: in asyncio 3.4.1+ StreamWriter.drain() is coroutine + # see bug #170 + if (asyncio.iscoroutine(ret) or + isinstance(ret, asyncio.Future)): + yield from ret + except Exception as exc: + new_exc = aiohttp.ClientRequestError( + 'Can not write request body for %s' % self.url) + new_exc.__context__ = exc + new_exc.__cause__ = exc + reader.set_exception(new_exc) + + self._writer = None - protocol = conn.protocol - assert protocol is not None - writer = StreamWriter( - protocol, self.loop, - on_chunk_sent=self._on_chunk_request_sent - ) + def send(self, writer, reader): + writer.set_tcp_cork(True) + request = aiohttp.Request(writer, self.method, self.path, self.version) if self.compress: - writer.enable_compression(self.compress) + request.add_compression_filter(self.compress) if self.chunked is not None: - writer.enable_chunking() + request.enable_chunked_encoding() + request.add_chunking_filter(self.chunked) # set default content-type if (self.method in self.POST_METHODS and @@ -610,170 +503,96 @@ class ClientRequest: hdrs.CONTENT_TYPE not in self.headers): self.headers[hdrs.CONTENT_TYPE] = 'application/octet-stream' - # set the connection header - connection = self.headers.get(hdrs.CONNECTION) - if not connection: - if self.keep_alive(): - if self.version == HttpVersion10: - connection = 'keep-alive' - else: - if self.version == HttpVersion11: - connection = 'close' - - if connection is not None: - self.headers[hdrs.CONNECTION] = connection - - # status + headers - status_line = '{0} {1} HTTP/{2[0]}.{2[1]}'.format( - self.method, path, self.version) - await writer.write_headers(status_line, self.headers) - - self._writer = self.loop.create_task(self.write_bytes(writer, conn)) - - response_class = self.response_class - assert response_class is not None - self.response = response_class( - self.method, self.original_url, - writer=self._writer, continue100=self._continue, timer=self._timer, - request_info=self.request_info, - traces=self._traces, - loop=self.loop, - session=self._session - ) + for k, value in self.headers.items(): + request.add_header(k, value) + request.send_headers() + + self._writer = helpers.ensure_future( + self.write_bytes(request, reader), loop=self.loop) + + self.response = self.response_class( + self.method, self.url, self.host, + writer=self._writer, continue100=self._continue, + timeout=self._timeout) + self.response._post_init(self.loop) return self.response - async def close(self) -> None: + @asyncio.coroutine + def close(self): if self._writer is not None: try: - await self._writer + yield from self._writer finally: self._writer = None - def terminate(self) -> None: + def terminate(self): if self._writer is not None: if not self.loop.is_closed(): self._writer.cancel() self._writer = None - async def _on_chunk_request_sent(self, chunk: bytes) -> None: - for trace in self._traces: - await trace.send_request_chunk_sent(chunk) - -class ClientResponse(HeadersMixin): +class ClientResponse: # from the Status-Line of the response version = None # HTTP-Version - status = None # type: int # Status-Code + status = None # Status-Code reason = None # Reason-Phrase - content = None # type: StreamReader # Payload stream - _headers = None # type: CIMultiDictProxy[str] # Response headers - _raw_headers = None # type: RawHeaders # Response raw headers + cookies = None # Response cookies (Set-Cookie) + content = None # Payload stream + headers = None # Response headers, CIMultiDictProxy + raw_headers = None # Response raw headers, a sequence of pairs _connection = None # current connection + flow_control_class = FlowControlStreamReader # reader flow control + _reader = None # input stream + _response_parser = aiohttp.HttpResponseParser() _source_traceback = None # setted up by ClientRequest after ClientResponse object creation # post-init stage allows to not change ctor signature + _loop = None _closed = True # to allow __del__ for non-initialized properly response - _released = False - - def __init__(self, method: str, url: URL, *, - writer: 'asyncio.Task[None]', - continue100: Optional['asyncio.Future[bool]'], - timer: BaseTimerContext, - request_info: RequestInfo, - traces: List['Trace'], - loop: asyncio.AbstractEventLoop, - session: 'ClientSession') -> None: - assert isinstance(url, URL) + + def __init__(self, method, url, host='', *, writer=None, continue100=None, + timeout=5*60): + super().__init__() self.method = method - self.cookies = SimpleCookie() + self.url = url + self.host = host + self._content = None + self._writer = writer + self._continue = continue100 + self._closed = False + self._should_close = True # override by message.should_close later + self._history = () + self._timeout = timeout - self._real_url = url - self._url = url.with_fragment(None) - self._body = None # type: Any - self._writer = writer # type: Optional[asyncio.Task[None]] - self._continue = continue100 # None by default - self._closed = True - self._history = () # type: Tuple[ClientResponse, ...] - self._request_info = request_info - self._timer = timer if timer is not None else TimerNoop() - self._cache = {} # type: Dict[str, Any] - self._traces = traces + def _post_init(self, loop): self._loop = loop - # store a reference to session #1985 - self._session = session # type: Optional[ClientSession] if loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1)) - @reify - def url(self) -> URL: - return self._url - - @reify - def url_obj(self) -> URL: - warnings.warn( - "Deprecated, use .url #1654", DeprecationWarning, stacklevel=2) - return self._url - - @reify - def real_url(self) -> URL: - return self._real_url - - @reify - def host(self) -> str: - assert self._url.host is not None - return self._url.host - - @reify - def headers(self) -> 'CIMultiDictProxy[str]': - return self._headers - - @reify - def raw_headers(self) -> RawHeaders: - return self._raw_headers - - @reify - def request_info(self) -> RequestInfo: - return self._request_info - - @reify - def content_disposition(self) -> Optional[ContentDisposition]: - raw = self._headers.get(hdrs.CONTENT_DISPOSITION) - if raw is None: - return None - disposition_type, params_dct = multipart.parse_content_disposition(raw) - params = MappingProxyType(params_dct) - filename = multipart.content_disposition_filename(params) - return ContentDisposition(disposition_type, params, filename) - - def __del__(self, _warnings: Any=warnings) -> None: + def __del__(self, _warnings=warnings): + if self._loop is None: + return # not started if self._closed: return + self.close() - if self._connection is not None: - self._connection.release() - self._cleanup_writer() + _warnings.warn("Unclosed response {!r}".format(self), + ResourceWarning) + context = {'client_response': self, + 'message': 'Unclosed response'} + if self._source_traceback: + context['source_traceback'] = self._source_traceback + self._loop.call_exception_handler(context) - if self._loop.get_debug(): - if PY_36: - kwargs = {'source': self} - else: - kwargs = {} - _warnings.warn("Unclosed response {!r}".format(self), - ResourceWarning, - **kwargs) - context = {'client_response': self, - 'message': 'Unclosed response'} - if self._source_traceback: - context['source_traceback'] = self._source_traceback - self._loop.call_exception_handler(context) - - def __repr__(self) -> str: + def __repr__(self): out = io.StringIO() - ascii_encodable_url = str(self.url) + ascii_encodable_url = self.url.encode('ascii', 'backslashreplace') \ + .decode('ascii') if self.reason: ascii_encodable_reason = self.reason.encode('ascii', 'backslashreplace') \ @@ -787,130 +606,80 @@ class ClientResponse(HeadersMixin): return out.getvalue() @property - def connection(self) -> Optional['Connection']: + def connection(self): return self._connection - @reify - def history(self) -> Tuple['ClientResponse', ...]: - """A sequence of of responses, if redirects occurred.""" + @property + def history(self): + """A sequence of of responses, if redirects occured.""" return self._history - @reify - def links(self) -> 'MultiDictProxy[MultiDictProxy[Union[str, URL]]]': - links_str = ", ".join(self.headers.getall("link", [])) - - if not links_str: - return MultiDictProxy(MultiDict()) - - links = MultiDict() # type: MultiDict[MultiDictProxy[Union[str, URL]]] - - for val in re.split(r",(?=\s*<)", links_str): - match = re.match(r"\s*<(.*)>(.*)", val) - if match is None: # pragma: no cover - # the check exists to suppress mypy error - continue - url, params_str = match.groups() - params = params_str.split(";")[1:] - - link = MultiDict() # type: MultiDict[Union[str, URL]] - - for param in params: - match = re.match( - r"^\s*(\S*)\s*=\s*(['\"]?)(.*?)(\2)\s*$", - param, re.M - ) - if match is None: # pragma: no cover - # the check exists to suppress mypy error - continue - key, _, value, _ = match.groups() - - link.add(key, value) + def waiting_for_continue(self): + return self._continue is not None - key = link.get("rel", url) # type: ignore - - link.add("url", self.url.join(URL(url))) - - links.add(key, MultiDictProxy(link)) + def _setup_connection(self, connection): + self._reader = connection.reader + self._connection = connection + self.content = self.flow_control_class( + connection.reader, loop=connection.loop, timeout=self._timeout) - return MultiDictProxy(links) + def _need_parse_response_body(self): + return (self.method.lower() != 'head' and + self.status not in [204, 304]) - async def start(self, connection: 'Connection') -> 'ClientResponse': + @asyncio.coroutine + def start(self, connection, read_until_eof=False): """Start response processing.""" - self._closed = False - self._protocol = connection.protocol - self._connection = connection + self._setup_connection(connection) - with self._timer: - while True: - # read response - try: - message, payload = await self._protocol.read() # type: ignore # noqa - except http.HttpProcessingError as exc: - raise ClientResponseError( - self.request_info, self.history, - status=exc.code, - message=exc.message, headers=exc.headers) from exc + while True: + httpstream = self._reader.set_parser(self._response_parser) - if (message.code < 100 or - message.code > 199 or message.code == 101): - break + # read response + with Timeout(self._timeout, loop=self._loop): + message = yield from httpstream.read() + if message.code != 100: + break - if self._continue is not None: - set_result(self._continue, True) - self._continue = None - - # payload eof handler - payload.on_eof(self._response_eof) + if self._continue is not None and not self._continue.done(): + self._continue.set_result(True) + self._continue = None # response status self.version = message.version self.status = message.code self.reason = message.reason + self._should_close = message.should_close # headers - self._headers = message.headers # type is CIMultiDictProxy - self._raw_headers = message.raw_headers # type is Tuple[bytes, bytes] + self.headers = CIMultiDictProxy(message.headers) + self.raw_headers = tuple(message.raw_headers) # payload - self.content = payload + rwb = self._need_parse_response_body() + self._reader.set_parser( + aiohttp.HttpPayloadParser(message, + readall=read_until_eof, + response_with_body=rwb), + self.content) # cookies - for hdr in self.headers.getall(hdrs.SET_COOKIE, ()): - try: - self.cookies.load(hdr) - except CookieError as exc: - client_logger.warning( - 'Can not load response cookies: %s', exc) + self.cookies = http.cookies.SimpleCookie() + if hdrs.SET_COOKIE in self.headers: + for hdr in self.headers.getall(hdrs.SET_COOKIE): + try: + self.cookies.load(hdr) + except http.cookies.CookieError as exc: + client_logger.warning( + 'Can not load response cookies: %s', exc) return self - def _response_eof(self) -> None: + def close(self): if self._closed: return - if self._connection is not None: - # websocket, protocol could be None because - # connection could be detached - if (self._connection.protocol is not None and - self._connection.protocol.upgraded): - return - - self._connection.release() - self._connection = None - self._closed = True - self._cleanup_writer() - - @property - def closed(self) -> bool: - return self._closed - def close(self) -> None: - if not self._released: - self._notify_content() - if self._closed: - return - - self._closed = True if self._loop is None or self._loop.is_closed(): return @@ -919,134 +688,114 @@ class ClientResponse(HeadersMixin): self._connection = None self._cleanup_writer() - def release(self) -> Any: - if not self._released: - self._notify_content() + @asyncio.coroutine + def release(self): if self._closed: - return noop() - - self._closed = True - if self._connection is not None: - self._connection.release() + return + try: + content = self.content + if content is not None and not content.at_eof(): + chunk = yield from content.readany() + while chunk is not EOF_MARKER or chunk: + chunk = yield from content.readany() + except Exception: + self._connection.close() self._connection = None + raise + finally: + self._closed = True + if self._connection is not None: + self._connection.release() + if self._reader is not None: + self._reader.unset_parser() + self._connection = None + self._cleanup_writer() - self._cleanup_writer() - return noop() - - def raise_for_status(self) -> None: + def raise_for_status(self): if 400 <= self.status: - # reason should always be not None for a started response - assert self.reason is not None - self.release() - raise ClientResponseError( - self.request_info, - self.history, - status=self.status, - message=self.reason, - headers=self.headers) - - def _cleanup_writer(self) -> None: - if self._writer is not None: + raise aiohttp.HttpProcessingError( + code=self.status, + message=self.reason) + + def _cleanup_writer(self): + if self._writer is not None and not self._writer.done(): self._writer.cancel() self._writer = None - self._session = None - def _notify_content(self) -> None: - content = self.content - if content and content.exception() is None: - content.set_exception( - ClientConnectionError('Connection closed')) - self._released = True - - async def wait_for_close(self) -> None: + @asyncio.coroutine + def wait_for_close(self): if self._writer is not None: try: - await self._writer + yield from self._writer finally: self._writer = None - self.release() + yield from self.release() - async def read(self) -> bytes: + @asyncio.coroutine + def read(self): """Read response payload.""" - if self._body is None: + if self._content is None: try: - self._body = await self.content.read() - for trace in self._traces: - await trace.send_response_chunk_received(self._body) - except BaseException: + self._content = yield from self.content.read() + except: self.close() raise - elif self._released: - raise ClientConnectionError('Connection closed') + else: + yield from self.release() - return self._body + return self._content - def get_encoding(self) -> str: + def _get_encoding(self): ctype = self.headers.get(hdrs.CONTENT_TYPE, '').lower() - mimetype = helpers.parse_mimetype(ctype) + mtype, stype, _, params = helpers.parse_mimetype(ctype) - encoding = mimetype.parameters.get('charset') - if encoding: - try: - codecs.lookup(encoding) - except LookupError: - encoding = None + encoding = params.get('charset') if not encoding: - if mimetype.type == 'application' and mimetype.subtype == 'json': - # RFC 7159 states that the default encoding is UTF-8. - encoding = 'utf-8' - else: - encoding = chardet.detect(self._body)['encoding'] + encoding = chardet.detect(self._content)['encoding'] if not encoding: encoding = 'utf-8' return encoding - async def text(self, - encoding: Optional[str]=None, errors: str='strict') -> str: + @asyncio.coroutine + def text(self, encoding=None): """Read response payload and decode.""" - if self._body is None: - await self.read() + if self._content is None: + yield from self.read() if encoding is None: - encoding = self.get_encoding() + encoding = self._get_encoding() - return self._body.decode(encoding, errors=errors) # type: ignore + return self._content.decode(encoding) - async def json(self, *, encoding: str=None, - loads: JSONDecoder=DEFAULT_JSON_DECODER, - content_type: Optional[str]='application/json') -> Any: + @asyncio.coroutine + def json(self, *, encoding=None, loads=json.loads): """Read and decodes JSON response.""" - if self._body is None: - await self.read() - - if content_type: - ctype = self.headers.get(hdrs.CONTENT_TYPE, '').lower() - if not _is_expected_content_type(ctype, content_type): - raise ContentTypeError( - self.request_info, - self.history, - message=('Attempt to decode JSON with ' - 'unexpected mimetype: %s' % ctype), - headers=self.headers) - - stripped = self._body.strip() # type: ignore + if self._content is None: + yield from self.read() + + ctype = self.headers.get(hdrs.CONTENT_TYPE, '').lower() + if 'json' not in ctype: + client_logger.warning( + 'Attempt to decode JSON with unexpected mimetype: %s', ctype) + + stripped = self._content.strip() if not stripped: return None if encoding is None: - encoding = self.get_encoding() + encoding = self._get_encoding() return loads(stripped.decode(encoding)) - async def __aenter__(self) -> 'ClientResponse': - return self + if PY_35: + @asyncio.coroutine + def __aenter__(self): + return self - async def __aexit__(self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType]) -> None: - # similar to _RequestContextManager, we do not need to check - # for exceptions, response object can closes connection - # is state is broken - self.release() + @asyncio.coroutine + def __aexit__(self, exc_type, exc_val, exc_tb): + if exc_type is None: + yield from self.release() + else: + self.close() diff --git a/venv/Lib/site-packages/aiohttp/client_ws.py b/venv/Lib/site-packages/aiohttp/client_ws.py index e5fd126a..984669c1 100644 --- a/venv/Lib/site-packages/aiohttp/client_ws.py +++ b/venv/Lib/site-packages/aiohttp/client_ws.py @@ -1,46 +1,19 @@ """WebSocket client for asyncio.""" import asyncio -from typing import Any, Optional +import json +import sys -import async_timeout +from ._ws_impl import CLOSED_MESSAGE, WebSocketError, WSMessage, WSMsgType -from .client_exceptions import ClientError -from .client_reqrep import ClientResponse -from .helpers import call_later, set_result -from .http import ( - WS_CLOSED_MESSAGE, - WS_CLOSING_MESSAGE, - WebSocketError, - WSMessage, - WSMsgType, -) -from .http_websocket import WebSocketWriter # WSMessage -from .streams import EofStream, FlowControlDataQueue # noqa -from .typedefs import ( - DEFAULT_JSON_DECODER, - DEFAULT_JSON_ENCODER, - JSONDecoder, - JSONEncoder, -) +PY_35 = sys.version_info >= (3, 5) +PY_352 = sys.version_info >= (3, 5, 2) class ClientWebSocketResponse: - def __init__(self, - reader: 'FlowControlDataQueue[WSMessage]', - writer: WebSocketWriter, - protocol: Optional[str], - response: ClientResponse, - timeout: float, - autoclose: bool, - autoping: bool, - loop: asyncio.AbstractEventLoop, - *, - receive_timeout: Optional[float]=None, - heartbeat: Optional[float]=None, - compress: int=0, - client_notakeover: bool=False) -> None: + def __init__(self, reader, writer, protocol, + response, timeout, autoclose, autoping, loop): self._response = response self._conn = response.connection @@ -49,128 +22,63 @@ class ClientWebSocketResponse: self._protocol = protocol self._closed = False self._closing = False - self._close_code = None # type: Optional[int] + self._close_code = None self._timeout = timeout - self._receive_timeout = receive_timeout self._autoclose = autoclose self._autoping = autoping - self._heartbeat = heartbeat - self._heartbeat_cb = None - if heartbeat is not None: - self._pong_heartbeat = heartbeat / 2.0 - self._pong_response_cb = None self._loop = loop - self._waiting = None # type: Optional[asyncio.Future[bool]] - self._exception = None # type: Optional[BaseException] - self._compress = compress - self._client_notakeover = client_notakeover - - self._reset_heartbeat() - - def _cancel_heartbeat(self) -> None: - if self._pong_response_cb is not None: - self._pong_response_cb.cancel() - self._pong_response_cb = None - - if self._heartbeat_cb is not None: - self._heartbeat_cb.cancel() - self._heartbeat_cb = None - - def _reset_heartbeat(self) -> None: - self._cancel_heartbeat() - - if self._heartbeat is not None: - self._heartbeat_cb = call_later( - self._send_heartbeat, self._heartbeat, self._loop) - - def _send_heartbeat(self) -> None: - if self._heartbeat is not None and not self._closed: - # fire-and-forget a task is not perfect but maybe ok for - # sending ping. Otherwise we need a long-living heartbeat - # task in the class. - self._loop.create_task(self._writer.ping()) - - if self._pong_response_cb is not None: - self._pong_response_cb.cancel() - self._pong_response_cb = call_later( - self._pong_not_received, self._pong_heartbeat, self._loop) - - def _pong_not_received(self) -> None: - if not self._closed: - self._closed = True - self._close_code = 1006 - self._exception = asyncio.TimeoutError() - self._response.close() + self._waiting = False + self._exception = None @property - def closed(self) -> bool: + def closed(self): return self._closed @property - def close_code(self) -> Optional[int]: + def close_code(self): return self._close_code @property - def protocol(self) -> Optional[str]: + def protocol(self): return self._protocol - @property - def compress(self) -> int: - return self._compress - - @property - def client_notakeover(self) -> bool: - return self._client_notakeover - - def get_extra_info(self, name: str, default: Any=None) -> Any: - """extra info from connection transport""" - conn = self._response.connection - if conn is None: - return default - transport = conn.transport - if transport is None: - return default - return transport.get_extra_info(name, default) - - def exception(self) -> Optional[BaseException]: + def exception(self): return self._exception - async def ping(self, message: bytes=b'') -> None: - await self._writer.ping(message) + def ping(self, message='b'): + if self._closed: + raise RuntimeError('websocket connection is closed') + self._writer.ping(message) - async def pong(self, message: bytes=b'') -> None: - await self._writer.pong(message) + def pong(self, message='b'): + if self._closed: + raise RuntimeError('websocket connection is closed') + self._writer.pong(message) - async def send_str(self, data: str, - compress: Optional[int]=None) -> None: + def send_str(self, data): + if self._closed: + raise RuntimeError('websocket connection is closed') if not isinstance(data, str): raise TypeError('data argument must be str (%r)' % type(data)) - await self._writer.send(data, binary=False, compress=compress) + self._writer.send(data, binary=False) - async def send_bytes(self, data: bytes, - compress: Optional[int]=None) -> None: + def send_bytes(self, data): + if self._closed: + raise RuntimeError('websocket connection is closed') if not isinstance(data, (bytes, bytearray, memoryview)): raise TypeError('data argument must be byte-ish (%r)' % type(data)) - await self._writer.send(data, binary=True, compress=compress) + self._writer.send(data, binary=True) - async def send_json(self, data: Any, - compress: Optional[int]=None, - *, dumps: JSONEncoder=DEFAULT_JSON_ENCODER) -> None: - await self.send_str(dumps(data), compress=compress) - - async def close(self, *, code: int=1000, message: bytes=b'') -> bool: - # we need to break `receive()` cycle first, - # `close()` may be called from different task - if self._waiting is not None and not self._closed: - self._reader.feed_data(WS_CLOSING_MESSAGE, 0) - await self._waiting + def send_json(self, data, *, dumps=json.dumps): + self.send_str(dumps(data)) + @asyncio.coroutine + def close(self, *, code=1000, message=b''): if not self._closed: - self._cancel_heartbeat() self._closed = True try: - await self._writer.close(code, message) + self._writer.close(code, message) except asyncio.CancelledError: self._close_code = 1006 self._response.close() @@ -187,8 +95,8 @@ class ClientWebSocketResponse: while True: try: - with async_timeout.timeout(self._timeout, loop=self._loop): - msg = await self._reader.read() + msg = yield from asyncio.wait_for( + self._reader.read(), self._timeout, loop=self._loop) except asyncio.CancelledError: self._close_code = 1006 self._response.close() @@ -206,96 +114,80 @@ class ClientWebSocketResponse: else: return False - async def receive(self, timeout: Optional[float]=None) -> WSMessage: - while True: - if self._waiting is not None: - raise RuntimeError( - 'Concurrent call to receive() is not allowed') + @asyncio.coroutine + def receive(self): + if self._waiting: + raise RuntimeError('Concurrent call to receive() is not allowed') - if self._closed: - return WS_CLOSED_MESSAGE - elif self._closing: - await self.close() - return WS_CLOSED_MESSAGE + self._waiting = True + try: + while True: + if self._closed: + return CLOSED_MESSAGE - try: - self._waiting = self._loop.create_future() try: - with async_timeout.timeout( - timeout or self._receive_timeout, - loop=self._loop): - msg = await self._reader.read() - self._reset_heartbeat() - finally: - waiter = self._waiting - self._waiting = None - set_result(waiter, True) - except (asyncio.CancelledError, asyncio.TimeoutError): - self._close_code = 1006 - raise - except EofStream: - self._close_code = 1000 - await self.close() - return WSMessage(WSMsgType.CLOSED, None, None) - except ClientError: - self._closed = True - self._close_code = 1006 - return WS_CLOSED_MESSAGE - except WebSocketError as exc: - self._close_code = exc.code - await self.close(code=exc.code) - return WSMessage(WSMsgType.ERROR, exc, None) - except Exception as exc: - self._exception = exc - self._closing = True - self._close_code = 1006 - await self.close() - return WSMessage(WSMsgType.ERROR, exc, None) - - if msg.type == WSMsgType.CLOSE: - self._closing = True - self._close_code = msg.data - if not self._closed and self._autoclose: - await self.close() - elif msg.type == WSMsgType.CLOSING: - self._closing = True - elif msg.type == WSMsgType.PING and self._autoping: - await self.pong(msg.data) - continue - elif msg.type == WSMsgType.PONG and self._autoping: - continue - - return msg + msg = yield from self._reader.read() + except (asyncio.CancelledError, asyncio.TimeoutError): + raise + except WebSocketError as exc: + self._close_code = exc.code + yield from self.close(code=exc.code) + return WSMessage(WSMsgType.ERROR, exc, None) + except Exception as exc: + self._exception = exc + self._closing = True + self._close_code = 1006 + yield from self.close() + return WSMessage(WSMsgType.ERROR, exc, None) - async def receive_str(self, *, timeout: Optional[float]=None) -> str: - msg = await self.receive(timeout) + if msg.type == WSMsgType.CLOSE: + self._closing = True + self._close_code = msg.data + if not self._closed and self._autoclose: + yield from self.close() + return msg + if msg.type == WSMsgType.PING and self._autoping: + self.pong(msg.data) + elif msg.type == WSMsgType.PONG and self._autoping: + continue + else: + return msg + finally: + self._waiting = False + + @asyncio.coroutine + def receive_str(self): + msg = yield from self.receive() if msg.type != WSMsgType.TEXT: raise TypeError( "Received message {}:{!r} is not str".format(msg.type, msg.data)) return msg.data - async def receive_bytes(self, *, timeout: Optional[float]=None) -> bytes: - msg = await self.receive(timeout) + @asyncio.coroutine + def receive_bytes(self): + msg = yield from self.receive() if msg.type != WSMsgType.BINARY: raise TypeError( "Received message {}:{!r} is not bytes".format(msg.type, msg.data)) return msg.data - async def receive_json(self, - *, loads: JSONDecoder=DEFAULT_JSON_DECODER, - timeout: Optional[float]=None) -> Any: - data = await self.receive_str(timeout=timeout) + @asyncio.coroutine + def receive_json(self, *, loads=json.loads): + data = yield from self.receive_str() return loads(data) - def __aiter__(self) -> 'ClientWebSocketResponse': - return self + if PY_35: + def __aiter__(self): + return self + + if not PY_352: # pragma: no cover + __aiter__ = asyncio.coroutine(__aiter__) - async def __anext__(self) -> WSMessage: - msg = await self.receive() - if msg.type in (WSMsgType.CLOSE, - WSMsgType.CLOSING, - WSMsgType.CLOSED): - raise StopAsyncIteration # NOQA - return msg + @asyncio.coroutine + def __anext__(self): + msg = yield from self.receive() + if msg.type == WSMsgType.CLOSE: + raise StopAsyncIteration # NOQA + return msg diff --git a/venv/Lib/site-packages/aiohttp/connector.py b/venv/Lib/site-packages/aiohttp/connector.py index da37e0d9..8ada87a5 100644 --- a/venv/Lib/site-packages/aiohttp/connector.py +++ b/venv/Lib/site-packages/aiohttp/connector.py @@ -1,95 +1,35 @@ import asyncio import functools -import random +import http.cookies +import ssl import sys import traceback import warnings -from collections import defaultdict, deque -from contextlib import suppress -from http.cookies import SimpleCookie -from itertools import cycle, islice -from time import monotonic -from types import TracebackType -from typing import ( # noqa - TYPE_CHECKING, - Any, - Awaitable, - Callable, - DefaultDict, - Dict, - Iterator, - List, - Optional, - Set, - Tuple, - Type, - Union, - cast, -) - -import attr +from collections import defaultdict +from hashlib import md5, sha1, sha256 +from itertools import chain +from math import ceil +from types import MappingProxyType + +import aiohttp from . import hdrs, helpers -from .abc import AbstractResolver -from .client_exceptions import ( - ClientConnectionError, - ClientConnectorCertificateError, - ClientConnectorError, - ClientConnectorSSLError, - ClientHttpProxyError, - ClientProxyConnectionError, - ServerFingerprintMismatch, - cert_errors, - ssl_errors, -) -from .client_proto import ResponseHandler -from .client_reqrep import ClientRequest, Fingerprint, _merge_ssl_params -from .helpers import ( - PY_36, - CeilTimeout, - get_running_loop, - is_ip_address, - noop2, - sentinel, -) -from .http import RESPONSES -from .locks import EventResultOrError +from .client import ClientRequest +from .errors import (ClientOSError, ClientTimeoutError, FingerprintMismatch, + HttpProxyError, ProxyConnectionError, + ServerDisconnectedError) +from .helpers import is_ip_address, sentinel from .resolver import DefaultResolver -try: - import ssl - SSLContext = ssl.SSLContext -except ImportError: # pragma: no cover - ssl = None # type: ignore - SSLContext = object # type: ignore - - -__all__ = ('BaseConnector', 'TCPConnector', 'UnixConnector', - 'NamedPipeConnector') - - -if TYPE_CHECKING: # pragma: no cover - from .client import ClientTimeout # noqa - from .client_reqrep import ConnectionKey # noqa - from .tracing import Trace # noqa - +__all__ = ('BaseConnector', 'TCPConnector', 'ProxyConnector', 'UnixConnector') -class _DeprecationWaiter: - __slots__ = ('_awaitable', '_awaited') +PY_343 = sys.version_info >= (3, 4, 3) - def __init__(self, awaitable: Awaitable[Any]) -> None: - self._awaitable = awaitable - self._awaited = False - - def __await__(self) -> Any: - self._awaited = True - return self._awaitable.__await__() - - def __del__(self) -> None: - if not self._awaited: - warnings.warn("Connector.close() is a coroutine, " - "please use await connector.close()", - DeprecationWarning) +HASHFUNC_BY_DIGESTLEN = { + 16: md5, + 20: sha1, + 32: sha256, +} class Connection: @@ -97,36 +37,32 @@ class Connection: _source_traceback = None _transport = None - def __init__(self, connector: 'BaseConnector', - key: 'ConnectionKey', - protocol: ResponseHandler, - loop: asyncio.AbstractEventLoop) -> None: + def __init__(self, connector, key, request, transport, protocol, loop): self._key = key self._connector = connector + self._request = request + self._transport = transport + self._protocol = protocol self._loop = loop - self._protocol = protocol # type: Optional[ResponseHandler] - self._callbacks = [] # type: List[Callable[[], None]] + self.reader = protocol.reader + self.writer = protocol.writer if loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1)) - def __repr__(self) -> str: + def __repr__(self): return 'Connection<{}>'.format(self._key) - def __del__(self, _warnings: Any=warnings) -> None: - if self._protocol is not None: - if PY_36: - kwargs = {'source': self} - else: - kwargs = {} + def __del__(self, _warnings=warnings): + if self._transport is not None: _warnings.warn('Unclosed connection {!r}'.format(self), - ResourceWarning, - **kwargs) + ResourceWarning) if self._loop.is_closed(): return self._connector._release( - self._key, self._protocol, should_close=True) + self._key, self._request, self._transport, self._protocol, + should_close=True) context = {'client_connection': self, 'message': 'Unclosed connection'} @@ -135,87 +71,48 @@ class Connection: self._loop.call_exception_handler(context) @property - def loop(self) -> asyncio.AbstractEventLoop: - warnings.warn("connector.loop property is deprecated", - DeprecationWarning, - stacklevel=2) + def loop(self): return self._loop - @property - def transport(self) -> Optional[asyncio.Transport]: - if self._protocol is None: - return None - return self._protocol.transport - - @property - def protocol(self) -> Optional[ResponseHandler]: - return self._protocol - - def add_callback(self, callback: Callable[[], None]) -> None: - if callback is not None: - self._callbacks.append(callback) - - def _notify_release(self) -> None: - callbacks, self._callbacks = self._callbacks[:], [] - - for cb in callbacks: - with suppress(Exception): - cb() - - def close(self) -> None: - self._notify_release() - - if self._protocol is not None: + def close(self): + if self._transport is not None: self._connector._release( - self._key, self._protocol, should_close=True) - self._protocol = None - - def release(self) -> None: - self._notify_release() + self._key, self._request, self._transport, self._protocol, + should_close=True) + self._transport = None - if self._protocol is not None: + def release(self): + if self._transport is not None: self._connector._release( - self._key, self._protocol, - should_close=self._protocol.should_close) - self._protocol = None + self._key, self._request, self._transport, self._protocol, + should_close=False) + self._transport = None - @property - def closed(self) -> bool: - return self._protocol is None or not self._protocol.is_connected() - - -class _TransportPlaceholder: - """ placeholder for BaseConnector.connect function """ + def detach(self): + self._transport = None - def close(self) -> None: - pass + @property + def closed(self): + return self._transport is None -class BaseConnector: +class BaseConnector(object): """Base connector class. + conn_timeout - (optional) Connect timeout. keepalive_timeout - (optional) Keep-alive timeout. force_close - Set to True to force close and do reconnect after each request (and between redirects). - limit - The total number of simultaneous connections. - limit_per_host - Number of simultaneous connections to one host. - enable_cleanup_closed - Enables clean-up closed ssl transports. - Disabled by default. + limit - The limit of simultaneous connections to the same endpoint. loop - Optional event loop. """ _closed = True # prevent AttributeError in __del__ if ctor was failed _source_traceback = None - # abort transport after 2 seconds (cleanup broken connections) - _cleanup_closed_period = 2.0 - - def __init__(self, *, - keepalive_timeout: Union[object, None, float]=sentinel, - force_close: bool=False, - limit: int=100, limit_per_host: int=0, - enable_cleanup_closed: bool=False, - loop: Optional[asyncio.AbstractEventLoop]=None) -> None: + def __init__(self, *, conn_timeout=None, keepalive_timeout=sentinel, + force_close=False, limit=20, + loop=None): if force_close: if keepalive_timeout is not None and \ @@ -224,40 +121,32 @@ class BaseConnector: 'be set if force_close is True') else: if keepalive_timeout is sentinel: - keepalive_timeout = 15.0 + keepalive_timeout = 30 - loop = get_running_loop(loop) + if loop is None: + loop = asyncio.get_event_loop() self._closed = False if loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1)) - self._conns = {} # type: Dict[ConnectionKey, List[Tuple[ResponseHandler, float]]] # noqa - self._limit = limit - self._limit_per_host = limit_per_host - self._acquired = set() # type: Set[ResponseHandler] - self._acquired_per_host = defaultdict(set) # type: DefaultDict[ConnectionKey, Set[ResponseHandler]] # noqa - self._keepalive_timeout = cast(float, keepalive_timeout) + self._conns = {} + self._acquired = defaultdict(set) + self._conn_timeout = conn_timeout + self._keepalive_timeout = keepalive_timeout + self._cleanup_handle = None self._force_close = force_close - - # {host_key: FIFO list of waiters} - self._waiters = defaultdict(deque) # type: ignore + self._limit = limit + self._waiters = defaultdict(list) self._loop = loop - self._factory = functools.partial(ResponseHandler, loop=loop) - - self.cookies = SimpleCookie() - - # start keep-alive connection cleanup task - self._cleanup_handle = None + self._factory = functools.partial( + aiohttp.StreamProtocol, loop=loop, + disconnect_error=ServerDisconnectedError) - # start cleanup closed transports task - self._cleanup_closed_handle = None - self._cleanup_closed_disabled = not enable_cleanup_closed - self._cleanup_closed_transports = [] # type: List[Optional[asyncio.Transport]] # noqa - self._cleanup_closed() + self.cookies = http.cookies.SimpleCookie() - def __del__(self, _warnings: Any=warnings) -> None: + def __del__(self, _warnings=warnings): if self._closed: return if not self._conns: @@ -265,15 +154,10 @@ class BaseConnector: conns = [repr(c) for c in self._conns.values()] - self._close() + self.close() - if PY_36: - kwargs = {'source': self} - else: - kwargs = {} _warnings.warn("Unclosed connector {!r}".format(self), - ResourceWarning, - **kwargs) + ResourceWarning) context = {'connector': self, 'connections': conns, 'message': 'Unclosed connector'} @@ -281,766 +165,491 @@ class BaseConnector: context['source_traceback'] = self._source_traceback self._loop.call_exception_handler(context) - def __enter__(self) -> 'BaseConnector': - warnings.warn('"witn Connector():" is deprecated, ' - 'use "async with Connector():" instead', - DeprecationWarning) + def __enter__(self): return self - def __exit__(self, *exc: Any) -> None: + def __exit__(self, *exc): self.close() - async def __aenter__(self) -> 'BaseConnector': - return self - - async def __aexit__(self, - exc_type: Optional[Type[BaseException]]=None, - exc_value: Optional[BaseException]=None, - exc_traceback: Optional[TracebackType]=None - ) -> None: - await self.close() - @property - def force_close(self) -> bool: + def force_close(self): """Ultimately close connection on releasing if True.""" return self._force_close @property - def limit(self) -> int: - """The total number for simultaneous connections. - - If limit is 0 the connector has no limit. - The default limit size is 100. - """ - return self._limit - - @property - def limit_per_host(self) -> int: - """The limit_per_host for simultaneous connections - to the same endpoint. + def limit(self): + """The limit for simultaneous connections to the same endpoint. Endpoints are the same if they are have equal (host, port, is_ssl) triple. + If limit is None the connector has no limit. + The default limit size is 20. """ - return self._limit_per_host + return self._limit - def _cleanup(self) -> None: + def _cleanup(self): """Cleanup unused transports.""" if self._cleanup_handle: self._cleanup_handle.cancel() + self._cleanup_handle = None now = self._loop.time() + + connections = {} timeout = self._keepalive_timeout - if self._conns: - connections = {} - deadline = now - timeout - for key, conns in self._conns.items(): - alive = [] - for proto, use_time in conns: - if proto.is_connected(): - if use_time - deadline < 0: - transport = proto.transport - proto.close() - if (key.is_ssl and - not self._cleanup_closed_disabled): - self._cleanup_closed_transports.append( - transport) - else: - alive.append((proto, use_time)) - - if alive: - connections[key] = alive - - self._conns = connections - - if self._conns: - self._cleanup_handle = helpers.weakref_handle( - self, '_cleanup', timeout, self._loop) - - def _drop_acquired_per_host(self, key: 'ConnectionKey', - val: ResponseHandler) -> None: - acquired_per_host = self._acquired_per_host - if key not in acquired_per_host: - return - conns = acquired_per_host[key] - conns.remove(val) - if not conns: - del self._acquired_per_host[key] - - def _cleanup_closed(self) -> None: - """Double confirmation for transport close. - Some broken ssl servers may leave socket open without proper close. - """ - if self._cleanup_closed_handle: - self._cleanup_closed_handle.cancel() + for key, conns in self._conns.items(): + alive = [] + for transport, proto, t0 in conns: + if transport is not None: + if proto and not proto.is_connected(): + transport = None + else: + delta = t0 + self._keepalive_timeout - now + if delta < 0: + transport.close() + transport = None + elif delta < timeout: + timeout = delta - for transport in self._cleanup_closed_transports: - if transport is not None: - transport.abort() + if transport is not None: + alive.append((transport, proto, t0)) + if alive: + connections[key] = alive - self._cleanup_closed_transports = [] + if connections: + self._cleanup_handle = self._loop.call_at( + ceil(now + timeout), self._cleanup) - if not self._cleanup_closed_disabled: - self._cleanup_closed_handle = helpers.weakref_handle( - self, '_cleanup_closed', - self._cleanup_closed_period, self._loop) + self._conns = connections - def close(self) -> Awaitable[None]: - """Close all opened transports.""" - self._close() - return _DeprecationWaiter(noop2()) + def _start_cleanup_task(self): + if self._cleanup_handle is None: + now = self._loop.time() + self._cleanup_handle = self._loop.call_at( + ceil(now + self._keepalive_timeout), self._cleanup) - def _close(self) -> None: + def close(self): + """Close all opened transports.""" + ret = helpers.create_future(self._loop) + ret.set_result(None) if self._closed: - return - + return ret self._closed = True try: if self._loop.is_closed(): - return - - # cancel cleanup task - if self._cleanup_handle: - self._cleanup_handle.cancel() - - # cancel cleanup close task - if self._cleanup_closed_handle: - self._cleanup_closed_handle.cancel() + return ret - for data in self._conns.values(): - for proto, t0 in data: - proto.close() + for key, data in self._conns.items(): + for transport, proto, t0 in data: + transport.close() - for proto in self._acquired: - proto.close() + for transport in chain(*self._acquired.values()): + transport.close() - for transport in self._cleanup_closed_transports: - if transport is not None: - transport.abort() + if self._cleanup_handle: + self._cleanup_handle.cancel() finally: self._conns.clear() self._acquired.clear() - self._waiters.clear() self._cleanup_handle = None - self._cleanup_closed_transports.clear() - self._cleanup_closed_handle = None + return ret @property - def closed(self) -> bool: + def closed(self): """Is connector closed. A readonly property. """ return self._closed - def _available_connections(self, key: 'ConnectionKey') -> int: - """ - Return number of available connections taking into account - the limit, limit_per_host and the connection key. - - If it returns less than 1 means that there is no connections - availables. - """ - - if self._limit: - # total calc available connections - available = self._limit - len(self._acquired) - - # check limit per host - if (self._limit_per_host and available > 0 and - key in self._acquired_per_host): - acquired = self._acquired_per_host.get(key) - assert acquired is not None - available = self._limit_per_host - len(acquired) - - elif self._limit_per_host and key in self._acquired_per_host: - # check limit per host - acquired = self._acquired_per_host.get(key) - assert acquired is not None - available = self._limit_per_host - len(acquired) - else: - available = 1 + @asyncio.coroutine + def connect(self, req): + """Get from pool or create new connection.""" + key = (req.host, req.port, req.ssl) - return available + limit = self._limit + if limit is not None: + fut = helpers.create_future(self._loop) + waiters = self._waiters[key] - async def connect(self, req: 'ClientRequest', - traces: List['Trace'], - timeout: 'ClientTimeout') -> Connection: - """Get from pool or create new connection.""" - key = req.connection_key - available = self._available_connections(key) + # The limit defines the maximum number of concurrent connections + # for a key. Waiters must be counted against the limit, even before + # the underlying connection is created. + available = limit - len(waiters) - len(self._acquired[key]) - # Wait if there are no available connections. - if available <= 0: - fut = self._loop.create_future() + # Don't wait if there are connections available. + if available > 0: + fut.set_result(None) # This connection will now count towards the limit. - waiters = self._waiters[key] waiters.append(fut) - if traces: - for trace in traces: - await trace.send_connection_queued_start() + try: + if limit is not None: + yield from fut - try: - await fut - except BaseException as e: - # remove a waiter even if it was cancelled, normally it's - # removed when it's notified + transport, proto = self._get(key) + if transport is None: try: - waiters.remove(fut) - except ValueError: # fut may no longer be in list - pass - - raise e - finally: - if not waiters: - try: - del self._waiters[key] - except KeyError: - # the key was evicted before. - pass - - if traces: - for trace in traces: - await trace.send_connection_queued_end() - - proto = self._get(key) - if proto is None: - placeholder = cast(ResponseHandler, _TransportPlaceholder()) - self._acquired.add(placeholder) - self._acquired_per_host[key].add(placeholder) - - if traces: - for trace in traces: - await trace.send_connection_create_start() - - try: - proto = await self._create_connection(req, traces, timeout) - if self._closed: - proto.close() - raise ClientConnectionError("Connector is closed.") - except BaseException: - if not self._closed: - self._acquired.remove(placeholder) - self._drop_acquired_per_host(key, placeholder) - self._release_waiter() - raise - else: - if not self._closed: - self._acquired.remove(placeholder) - self._drop_acquired_per_host(key, placeholder) - - if traces: - for trace in traces: - await trace.send_connection_create_end() - else: - if traces: - for trace in traces: - await trace.send_connection_reuseconn() - - self._acquired.add(proto) - self._acquired_per_host[key].add(proto) - return Connection(self, key, proto, self._loop) - - def _get(self, key: 'ConnectionKey') -> Optional[ResponseHandler]: + if self._conn_timeout: + transport, proto = yield from asyncio.wait_for( + self._create_connection(req), + self._conn_timeout, loop=self._loop) + else: + transport, proto = \ + yield from self._create_connection(req) + + except asyncio.TimeoutError as exc: + raise ClientTimeoutError( + 'Connection timeout to host {0[0]}:{0[1]} ssl:{0[2]}' + .format(key)) from exc + except OSError as exc: + raise ClientOSError( + exc.errno, + 'Cannot connect to host {0[0]}:{0[1]} ssl:{0[2]} [{1}]' + .format(key, exc.strerror)) from exc + except: + self._release_waiter(key) + raise + + self._acquired[key].add(transport) + conn = Connection(self, key, req, transport, proto, self._loop) + return conn + + def _get(self, key): try: conns = self._conns[key] except KeyError: - return None - + return None, None t1 = self._loop.time() while conns: - proto, t0 = conns.pop() - if proto.is_connected(): + transport, proto, t0 = conns.pop() + if transport is not None and proto.is_connected(): if t1 - t0 > self._keepalive_timeout: - transport = proto.transport - proto.close() - # only for SSL transports - if key.is_ssl and not self._cleanup_closed_disabled: - self._cleanup_closed_transports.append(transport) + transport.close() + transport = None else: if not conns: # The very last connection was reclaimed: drop the key del self._conns[key] - return proto - + return transport, proto # No more connections: drop the key del self._conns[key] - return None + return None, None - def _release_waiter(self) -> None: - """ - Iterates over all waiters till found one that is not finsihed and - belongs to a host that has available connections. - """ - if not self._waiters: - return + def _release_waiter(self, key): + waiters = self._waiters[key] + while waiters: + waiter = waiters.pop(0) + if not waiter.done(): + waiter.set_result(None) + break - # Having the dict keys ordered this avoids to iterate - # at the same order at each call. - queues = list(self._waiters.keys()) - random.shuffle(queues) - - for key in queues: - if self._available_connections(key) < 1: - continue - - waiters = self._waiters[key] - while waiters: - waiter = waiters.popleft() - if not waiter.done(): - waiter.set_result(None) - return - - def _release_acquired(self, key: 'ConnectionKey', - proto: ResponseHandler) -> None: + def _release(self, key, req, transport, protocol, *, should_close=False): if self._closed: # acquired connection is already released on connector closing return + acquired = self._acquired[key] try: - self._acquired.remove(proto) - self._drop_acquired_per_host(key, proto) + acquired.remove(transport) except KeyError: # pragma: no cover # this may be result of undetermenistic order of objects # finalization due garbage collection. pass else: - self._release_waiter() - - def _release(self, key: 'ConnectionKey', protocol: ResponseHandler, - *, should_close: bool=False) -> None: - if self._closed: - # acquired connection is already released on connector closing - return - - self._release_acquired(key, protocol) + if self._limit is not None and len(acquired) < self._limit: + self._release_waiter(key) - if self._force_close: - should_close = True + resp = req.response - if should_close or protocol.should_close: - transport = protocol.transport - protocol.close() + if not should_close: + if self._force_close: + should_close = True + elif resp is not None: + should_close = resp._should_close - if key.is_ssl and not self._cleanup_closed_disabled: - self._cleanup_closed_transports.append(transport) + reader = protocol.reader + if should_close or (reader.output and not reader.output.at_eof()): + transport.close() else: conns = self._conns.get(key) if conns is None: conns = self._conns[key] = [] - conns.append((protocol, self._loop.time())) + conns.append((transport, protocol, self._loop.time())) + reader.unset_parser() - if self._cleanup_handle is None: - self._cleanup_handle = helpers.weakref_handle( - self, '_cleanup', self._keepalive_timeout, self._loop) + self._start_cleanup_task() - async def _create_connection(self, req: 'ClientRequest', - traces: List['Trace'], - timeout: 'ClientTimeout') -> ResponseHandler: + @asyncio.coroutine + def _create_connection(self, req): raise NotImplementedError() -class _DNSCacheTable: - - def __init__(self, ttl: Optional[float]=None) -> None: - self._addrs_rr = {} # type: Dict[Tuple[str, int], Tuple[Iterator[Dict[str, Any]], int]] # noqa - self._timestamps = {} # type: Dict[Tuple[str, int], float] - self._ttl = ttl - - def __contains__(self, host: object) -> bool: - return host in self._addrs_rr - - def add(self, key: Tuple[str, int], addrs: List[Dict[str, Any]]) -> None: - self._addrs_rr[key] = (cycle(addrs), len(addrs)) - - if self._ttl: - self._timestamps[key] = monotonic() - - def remove(self, key: Tuple[str, int]) -> None: - self._addrs_rr.pop(key, None) - - if self._ttl: - self._timestamps.pop(key, None) - - def clear(self) -> None: - self._addrs_rr.clear() - self._timestamps.clear() - - def next_addrs(self, key: Tuple[str, int]) -> List[Dict[str, Any]]: - loop, length = self._addrs_rr[key] - addrs = list(islice(loop, length)) - # Consume one more element to shift internal state of `cycle` - next(loop) - return addrs - - def expired(self, key: Tuple[str, int]) -> bool: - if self._ttl is None: - return False - - return self._timestamps[key] + self._ttl < monotonic() +_SSL_OP_NO_COMPRESSION = getattr(ssl, "OP_NO_COMPRESSION", 0) class TCPConnector(BaseConnector): """TCP connector. verify_ssl - Set to True to check ssl certifications. - fingerprint - Pass the binary sha256 + fingerprint - Pass the binary md5, sha1, or sha256 digest of the expected certificate in DER format to verify that the certificate the server presents matches. See also https://en.wikipedia.org/wiki/Transport_Layer_Security#Certificate_pinning + resolve - (Deprecated) Set to True to do DNS lookup for + host name. resolver - Enable DNS lookups and use this resolver use_dns_cache - Use memory cache for DNS lookups. - ttl_dns_cache - Max seconds having cached a DNS entry, None forever. family - socket address family local_addr - local tuple of (host, port) to bind socket to + conn_timeout - (optional) Connect timeout. keepalive_timeout - (optional) Keep-alive timeout. force_close - Set to True to force close and do reconnect after each request (and between redirects). - limit - The total number of simultaneous connections. - limit_per_host - Number of simultaneous connections to one host. - enable_cleanup_closed - Enables clean-up closed ssl transports. - Disabled by default. + limit - The limit of simultaneous connections to the same endpoint. loop - Optional event loop. """ - def __init__(self, *, verify_ssl: bool=True, - fingerprint: Optional[bytes]=None, - use_dns_cache: bool=True, ttl_dns_cache: int=10, - family: int=0, - ssl_context: Optional[SSLContext]=None, - ssl: Union[None, bool, Fingerprint, SSLContext]=None, - local_addr: Optional[Tuple[str, int]]=None, - resolver: Optional[AbstractResolver]=None, - keepalive_timeout: Union[None, float, object]=sentinel, - force_close: bool=False, - limit: int=100, limit_per_host: int=0, - enable_cleanup_closed: bool=False, - loop: Optional[asyncio.AbstractEventLoop]=None): - super().__init__(keepalive_timeout=keepalive_timeout, - force_close=force_close, - limit=limit, limit_per_host=limit_per_host, - enable_cleanup_closed=enable_cleanup_closed, - loop=loop) - - self._ssl = _merge_ssl_params(ssl, verify_ssl, ssl_context, - fingerprint) + def __init__(self, *, verify_ssl=True, fingerprint=None, + resolve=sentinel, use_dns_cache=sentinel, + family=0, ssl_context=None, local_addr=None, resolver=None, + conn_timeout=None, keepalive_timeout=sentinel, + force_close=False, limit=20, + loop=None): + super().__init__(conn_timeout=conn_timeout, + keepalive_timeout=keepalive_timeout, + force_close=force_close, limit=limit, loop=loop) + + if not verify_ssl and ssl_context is not None: + raise ValueError( + "Either disable ssl certificate validation by " + "verify_ssl=False or specify ssl_context, not both.") + + self._verify_ssl = verify_ssl + + if fingerprint: + digestlen = len(fingerprint) + hashfunc = HASHFUNC_BY_DIGESTLEN.get(digestlen) + if not hashfunc: + raise ValueError('fingerprint has invalid length') + self._hashfunc = hashfunc + self._fingerprint = fingerprint + + if resolve is not sentinel: + warnings.warn(("resolve parameter is deprecated, " + "use use_dns_cache instead"), + DeprecationWarning, stacklevel=2) + + if use_dns_cache is not sentinel and resolve is not sentinel: + if use_dns_cache != resolve: + raise ValueError("use_dns_cache must agree with resolve") + _use_dns_cache = use_dns_cache + elif use_dns_cache is not sentinel: + _use_dns_cache = use_dns_cache + elif resolve is not sentinel: + _use_dns_cache = resolve + else: + _use_dns_cache = True + if resolver is None: resolver = DefaultResolver(loop=self._loop) self._resolver = resolver - self._use_dns_cache = use_dns_cache - self._cached_hosts = _DNSCacheTable(ttl=ttl_dns_cache) - self._throttle_dns_events = {} # type: Dict[Tuple[str, int], EventResultOrError] # noqa + self._use_dns_cache = _use_dns_cache + self._cached_hosts = {} + self._ssl_context = ssl_context self._family = family self._local_addr = local_addr - def close(self) -> Awaitable[None]: - """Close all ongoing DNS calls.""" - for ev in self._throttle_dns_events.values(): - ev.cancel() + @property + def verify_ssl(self): + """Do check for ssl certifications?""" + return self._verify_ssl + + @property + def fingerprint(self): + """Expected ssl certificate fingerprint.""" + return self._fingerprint + + @property + def ssl_context(self): + """SSLContext instance for https requests. - return super().close() + Lazy property, creates context on demand. + """ + if self._ssl_context is None: + if not self._verify_ssl: + sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + sslcontext.options |= ssl.OP_NO_SSLv2 + sslcontext.options |= ssl.OP_NO_SSLv3 + sslcontext.options |= _SSL_OP_NO_COMPRESSION + sslcontext.set_default_verify_paths() + else: + sslcontext = ssl.create_default_context() + self._ssl_context = sslcontext + return self._ssl_context @property - def family(self) -> int: + def family(self): """Socket family like AF_INET.""" return self._family @property - def use_dns_cache(self) -> bool: + def use_dns_cache(self): """True if local DNS caching is enabled.""" return self._use_dns_cache - def clear_dns_cache(self, - host: Optional[str]=None, - port: Optional[int]=None) -> None: + @property + def cached_hosts(self): + """Read-only dict of cached DNS record.""" + return MappingProxyType(self._cached_hosts) + + def clear_dns_cache(self, host=None, port=None): """Remove specified host/port or clear all dns local cache.""" if host is not None and port is not None: - self._cached_hosts.remove((host, port)) + self._cached_hosts.pop((host, port), None) elif host is not None or port is not None: raise ValueError("either both host and port " "or none of them are allowed") else: self._cached_hosts.clear() - async def _resolve_host(self, - host: str, port: int, - traces: Optional[List['Trace']]=None - ) -> List[Dict[str, Any]]: + @property + def resolve(self): + """Do DNS lookup for host name?""" + warnings.warn((".resolve property is deprecated, " + "use .dns_cache instead"), + DeprecationWarning, stacklevel=2) + return self.use_dns_cache + + @property + def resolved_hosts(self): + """The dict of (host, port) -> (ipaddr, port) pairs.""" + warnings.warn((".resolved_hosts property is deprecated, " + "use .cached_hosts instead"), + DeprecationWarning, stacklevel=2) + return self.cached_hosts + + def clear_resolved_hosts(self, host=None, port=None): + """Remove specified host/port or clear all resolve cache.""" + warnings.warn((".clear_resolved_hosts() is deprecated, " + "use .clear_dns_cache() instead"), + DeprecationWarning, stacklevel=2) + if host is not None and port is not None: + self.clear_dns_cache(host, port) + else: + self.clear_dns_cache() + + @asyncio.coroutine + def _resolve_host(self, host, port): if is_ip_address(host): return [{'hostname': host, 'host': host, 'port': port, 'family': self._family, 'proto': 0, 'flags': 0}] - if not self._use_dns_cache: - - if traces: - for trace in traces: - await trace.send_dns_resolvehost_start(host) - - res = (await self._resolver.resolve( - host, port, family=self._family)) - - if traces: - for trace in traces: - await trace.send_dns_resolvehost_end(host) - - return res + if self._use_dns_cache: + key = (host, port) - key = (host, port) - - if (key in self._cached_hosts) and \ - (not self._cached_hosts.expired(key)): - # get result early, before any await (#4014) - result = self._cached_hosts.next_addrs(key) - - if traces: - for trace in traces: - await trace.send_dns_cache_hit(host) - return result - - if key in self._throttle_dns_events: - # get event early, before any await (#4014) - event = self._throttle_dns_events[key] - if traces: - for trace in traces: - await trace.send_dns_cache_hit(host) - await event.wait() - else: - # update dict early, before any await (#4014) - self._throttle_dns_events[key] = \ - EventResultOrError(self._loop) - if traces: - for trace in traces: - await trace.send_dns_cache_miss(host) - try: - - if traces: - for trace in traces: - await trace.send_dns_resolvehost_start(host) - - addrs = await \ + if key not in self._cached_hosts: + self._cached_hosts[key] = yield from \ self._resolver.resolve(host, port, family=self._family) - if traces: - for trace in traces: - await trace.send_dns_resolvehost_end(host) - - self._cached_hosts.add(key, addrs) - self._throttle_dns_events[key].set() - except BaseException as e: - # any DNS exception, independently of the implementation - # is set for the waiters to raise the same exception. - self._throttle_dns_events[key].set(exc=e) - raise - finally: - self._throttle_dns_events.pop(key) - return self._cached_hosts.next_addrs(key) + return self._cached_hosts[key] + else: + res = yield from self._resolver.resolve( + host, port, family=self._family) + return res - async def _create_connection(self, req: 'ClientRequest', - traces: List['Trace'], - timeout: 'ClientTimeout') -> ResponseHandler: + @asyncio.coroutine + def _create_connection(self, req): """Create connection. Has same keyword arguments as BaseEventLoop.create_connection. """ if req.proxy: - _, proto = await self._create_proxy_connection( - req, traces, timeout) + transport, proto = yield from self._create_proxy_connection(req) else: - _, proto = await self._create_direct_connection( - req, traces, timeout) + transport, proto = yield from self._create_direct_connection(req) - return proto + return transport, proto - @staticmethod - @functools.lru_cache(None) - def _make_ssl_context(verified: bool) -> SSLContext: - if verified: - return ssl.create_default_context() - else: - sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - sslcontext.options |= ssl.OP_NO_SSLv2 - sslcontext.options |= ssl.OP_NO_SSLv3 - try: - sslcontext.options |= ssl.OP_NO_COMPRESSION - except AttributeError as attr_err: - warnings.warn( - '{!s}: The Python interpreter is compiled ' - 'against OpenSSL < 1.0.0. Ref: ' - 'https://docs.python.org/3/library/ssl.html' - '#ssl.OP_NO_COMPRESSION'. - format(attr_err), - ) - sslcontext.set_default_verify_paths() - return sslcontext - - def _get_ssl_context(self, req: 'ClientRequest') -> Optional[SSLContext]: - """Logic to get the correct SSL context - - 0. if req.ssl is false, return None - - 1. if ssl_context is specified in req, use it - 2. if _ssl_context is specified in self, use it - 3. otherwise: - 1. if verify_ssl is not specified in req, use self.ssl_context - (will generate a default context according to self.verify_ssl) - 2. if verify_ssl is True in req, generate a default SSL context - 3. if verify_ssl is False in req, generate a SSL context that - won't verify - """ - if req.is_ssl(): - if ssl is None: # pragma: no cover - raise RuntimeError('SSL is not supported.') - sslcontext = req.ssl - if isinstance(sslcontext, ssl.SSLContext): - return sslcontext - if sslcontext is not None: - # not verified or fingerprinted - return self._make_ssl_context(False) - sslcontext = self._ssl - if isinstance(sslcontext, ssl.SSLContext): - return sslcontext - if sslcontext is not None: - # not verified or fingerprinted - return self._make_ssl_context(False) - return self._make_ssl_context(True) + @asyncio.coroutine + def _create_direct_connection(self, req): + if req.ssl: + sslcontext = self.ssl_context else: - return None - - def _get_fingerprint(self, - req: 'ClientRequest') -> Optional['Fingerprint']: - ret = req.ssl - if isinstance(ret, Fingerprint): - return ret - ret = self._ssl - if isinstance(ret, Fingerprint): - return ret - return None - - async def _wrap_create_connection( - self, *args: Any, - req: 'ClientRequest', - timeout: 'ClientTimeout', - client_error: Type[Exception]=ClientConnectorError, - **kwargs: Any) -> Tuple[asyncio.Transport, ResponseHandler]: - try: - with CeilTimeout(timeout.sock_connect): - return await self._loop.create_connection(*args, **kwargs) # type: ignore # noqa - except cert_errors as exc: - raise ClientConnectorCertificateError( - req.connection_key, exc) from exc - except ssl_errors as exc: - raise ClientConnectorSSLError(req.connection_key, exc) from exc - except OSError as exc: - raise client_error(req.connection_key, exc) from exc - - async def _create_direct_connection( - self, - req: 'ClientRequest', - traces: List['Trace'], - timeout: 'ClientTimeout', - *, - client_error: Type[Exception]=ClientConnectorError - ) -> Tuple[asyncio.Transport, ResponseHandler]: - sslcontext = self._get_ssl_context(req) - fingerprint = self._get_fingerprint(req) + sslcontext = None - try: - # Cancelling this lookup should not cancel the underlying lookup - # or else the cancel event will get broadcast to all the waiters - # across all connections. - host = req.url.raw_host - assert host is not None - port = req.port - assert port is not None - hosts = await asyncio.shield(self._resolve_host( - host, - port, - traces=traces), loop=self._loop) - except OSError as exc: - # in case of proxy it is not ClientProxyConnectionError - # it is problem of resolving proxy ip itself - raise ClientConnectorError(req.connection_key, exc) from exc - - last_exc = None # type: Optional[Exception] + hosts = yield from self._resolve_host(req.host, req.port) + exc = None for hinfo in hosts: - host = hinfo['host'] - port = hinfo['port'] - try: - transp, proto = await self._wrap_create_connection( - self._factory, host, port, timeout=timeout, + host = hinfo['host'] + port = hinfo['port'] + transp, proto = yield from self._loop.create_connection( + self._factory, host, port, ssl=sslcontext, family=hinfo['family'], proto=hinfo['proto'], flags=hinfo['flags'], server_hostname=hinfo['hostname'] if sslcontext else None, - local_addr=self._local_addr, - req=req, client_error=client_error) - except ClientConnectorError as exc: - last_exc = exc - continue - - if req.is_ssl() and fingerprint: - try: - fingerprint.check(transp) - except ServerFingerprintMismatch as exc: - transp.close() - if not self._cleanup_closed_disabled: - self._cleanup_closed_transports.append(transp) - last_exc = exc - continue - - return transp, proto + local_addr=self._local_addr) + has_cert = transp.get_extra_info('sslcontext') + if has_cert and self._fingerprint: + sock = transp.get_extra_info('socket') + if not hasattr(sock, 'getpeercert'): + # Workaround for asyncio 3.5.0 + # Starting from 3.5.1 version + # there is 'ssl_object' extra info in transport + sock = transp._ssl_protocol._sslpipe.ssl_object + # gives DER-encoded cert as a sequence of bytes (or None) + cert = sock.getpeercert(binary_form=True) + assert cert + got = self._hashfunc(cert).digest() + expected = self._fingerprint + if got != expected: + transp.close() + raise FingerprintMismatch(expected, got, host, port) + return transp, proto + except OSError as e: + exc = e else: - assert last_exc is not None - raise last_exc - - async def _create_proxy_connection( - self, - req: 'ClientRequest', - traces: List['Trace'], - timeout: 'ClientTimeout' - ) -> Tuple[asyncio.Transport, ResponseHandler]: - headers = {} # type: Dict[str, str] - if req.proxy_headers is not None: - headers = req.proxy_headers # type: ignore - headers[hdrs.HOST] = req.headers[hdrs.HOST] - - url = req.proxy - assert url is not None + raise ClientOSError(exc.errno, + 'Can not connect to %s:%s [%s]' % + (req.host, req.port, exc.strerror)) from exc + + @asyncio.coroutine + def _create_proxy_connection(self, req): proxy_req = ClientRequest( - hdrs.METH_GET, url, - headers=headers, + hdrs.METH_GET, req.proxy, + headers={hdrs.HOST: req.host}, auth=req.proxy_auth, - loop=self._loop, - ssl=req.ssl) - - # create connection to proxy server - transport, proto = await self._create_direct_connection( - proxy_req, [], timeout, client_error=ClientProxyConnectionError) - - # Many HTTP proxies has buggy keepalive support. Let's not - # reuse connection but close it after processing every - # response. - proto.force_close() - - auth = proxy_req.headers.pop(hdrs.AUTHORIZATION, None) - if auth is not None: - if not req.is_ssl(): + loop=self._loop) + try: + # create connection to proxy server + transport, proto = yield from self._create_direct_connection( + proxy_req) + except OSError as exc: + raise ProxyConnectionError(*exc.args) from exc + + if not req.ssl: + req.path = '{scheme}://{host}{path}'.format(scheme=req.scheme, + host=req.netloc, + path=req.path) + if hdrs.AUTHORIZATION in proxy_req.headers: + auth = proxy_req.headers[hdrs.AUTHORIZATION] + del proxy_req.headers[hdrs.AUTHORIZATION] + if not req.ssl: req.headers[hdrs.PROXY_AUTHORIZATION] = auth else: proxy_req.headers[hdrs.PROXY_AUTHORIZATION] = auth - if req.is_ssl(): - sslcontext = self._get_ssl_context(req) + if req.ssl: # For HTTPS requests over HTTP proxy # we must notify proxy to tunnel connection # so we send CONNECT command: @@ -1051,143 +660,124 @@ class TCPConnector(BaseConnector): # to do this we must wrap raw socket into secure one # asyncio handles this perfectly proxy_req.method = hdrs.METH_CONNECT - proxy_req.url = req.url - key = attr.evolve(req.connection_key, - proxy=None, - proxy_auth=None, - proxy_headers_hash=None) - conn = Connection(self, key, proto, self._loop) - proxy_resp = await proxy_req.send(conn) + proxy_req.path = '{}:{}'.format(req.host, req.port) + key = (req.host, req.port, req.ssl) + conn = Connection(self, key, proxy_req, + transport, proto, self._loop) + self._acquired[key].add(conn._transport) + proxy_resp = proxy_req.send(conn.writer, conn.reader) try: - protocol = conn._protocol - assert protocol is not None - protocol.set_response_params() - resp = await proxy_resp.start(conn) - except BaseException: + resp = yield from proxy_resp.start(conn, True) + except: proxy_resp.close() conn.close() raise else: - conn._protocol = None - conn._transport = None - try: - if resp.status != 200: - message = resp.reason - if message is None: - message = RESPONSES[resp.status][0] - raise ClientHttpProxyError( - proxy_resp.request_info, - resp.history, - status=resp.status, - message=message, - headers=resp.headers) - rawsock = transport.get_extra_info('socket', default=None) - if rawsock is None: - raise RuntimeError( - "Transport does not expose socket instance") - # Duplicate the socket, so now we can close proxy transport - rawsock = rawsock.dup() - finally: - transport.close() - - transport, proto = await self._wrap_create_connection( - self._factory, timeout=timeout, - ssl=sslcontext, sock=rawsock, - server_hostname=req.host, - req=req) + conn.detach() + if resp.status != 200: + raise HttpProxyError(code=resp.status, message=resp.reason) + rawsock = transport.get_extra_info('socket', default=None) + if rawsock is None: + raise RuntimeError( + "Transport does not expose socket instance") + transport.pause_reading() + transport, proto = yield from self._loop.create_connection( + self._factory, ssl=self.ssl_context, sock=rawsock, + server_hostname=req.host) finally: proxy_resp.close() return transport, proto -class UnixConnector(BaseConnector): - """Unix socket connector. +class ProxyConnector(TCPConnector): + """Http Proxy connector. + Deprecated, use ClientSession.request with proxy parameters. + Is still here for backward compatibility. - path - Unix socket path. + proxy - Proxy URL address. Only HTTP proxy supported. + proxy_auth - (optional) Proxy HTTP Basic Auth + proxy_auth - aiohttp.helpers.BasicAuth + conn_timeout - (optional) Connect timeout. keepalive_timeout - (optional) Keep-alive timeout. force_close - Set to True to force close and do reconnect after each request (and between redirects). - limit - The total number of simultaneous connections. - limit_per_host - Number of simultaneous connections to one host. + limit - The limit of simultaneous connections to the same endpoint. loop - Optional event loop. + + Usage: + + >>> conn = ProxyConnector(proxy="http://some.proxy.com") + >>> session = ClientSession(connector=conn) + >>> resp = yield from session.get('http://python.org') + """ - def __init__(self, path: str, force_close: bool=False, - keepalive_timeout: Union[object, float, None]=sentinel, - limit: int=100, limit_per_host: int=0, - loop: Optional[asyncio.AbstractEventLoop]=None) -> None: + def __init__(self, proxy, *, proxy_auth=None, force_close=True, + conn_timeout=None, keepalive_timeout=sentinel, + limit=20, loop=None): + warnings.warn("ProxyConnector is deprecated, use " + "client.get(url, proxy=proxy_url) instead", + DeprecationWarning) super().__init__(force_close=force_close, + conn_timeout=conn_timeout, keepalive_timeout=keepalive_timeout, - limit=limit, limit_per_host=limit_per_host, loop=loop) - self._path = path + limit=limit, loop=loop) + self._proxy = proxy + self._proxy_auth = proxy_auth @property - def path(self) -> str: - """Path to unix socket.""" - return self._path + def proxy(self): + return self._proxy - async def _create_connection(self, req: 'ClientRequest', - traces: List['Trace'], - timeout: 'ClientTimeout') -> ResponseHandler: - try: - with CeilTimeout(timeout.sock_connect): - _, proto = await self._loop.create_unix_connection( - self._factory, self._path) - except OSError as exc: - raise ClientConnectorError(req.connection_key, exc) from exc + @property + def proxy_auth(self): + return self._proxy_auth - return cast(ResponseHandler, proto) + @asyncio.coroutine + def _create_connection(self, req): + """ + Use TCPConnector _create_connection, to emulate old ProxyConnector. + """ + req.update_proxy(self._proxy, self._proxy_auth) + transport, proto = yield from super()._create_connection(req) + return transport, proto -class NamedPipeConnector(BaseConnector): - """Named pipe connector. - Only supported by the proactor event loop. - See also: https://docs.python.org/3.7/library/asyncio-eventloop.html +class UnixConnector(BaseConnector): + """Unix socket connector. - path - Windows named pipe path. + path - Unix socket path. + conn_timeout - (optional) Connect timeout. keepalive_timeout - (optional) Keep-alive timeout. force_close - Set to True to force close and do reconnect after each request (and between redirects). - limit - The total number of simultaneous connections. - limit_per_host - Number of simultaneous connections to one host. + limit - The limit of simultaneous connections to the same endpoint. loop - Optional event loop. + + Usage: + + >>> conn = UnixConnector(path='/path/to/socket') + >>> session = ClientSession(connector=conn) + >>> resp = yield from session.get('http://python.org') + """ - def __init__(self, path: str, force_close: bool=False, - keepalive_timeout: Union[object, float, None]=sentinel, - limit: int=100, limit_per_host: int=0, - loop: Optional[asyncio.AbstractEventLoop]=None) -> None: + def __init__(self, path, force_close=False, conn_timeout=None, + keepalive_timeout=sentinel, limit=20, loop=None): super().__init__(force_close=force_close, + conn_timeout=conn_timeout, keepalive_timeout=keepalive_timeout, - limit=limit, limit_per_host=limit_per_host, loop=loop) - if not isinstance(self._loop, asyncio.ProactorEventLoop): # type: ignore # noqa - raise RuntimeError("Named Pipes only available in proactor " - "loop under windows") + limit=limit, loop=loop) self._path = path @property - def path(self) -> str: - """Path to the named pipe.""" + def path(self): + """Path to unix socket.""" return self._path - async def _create_connection(self, req: 'ClientRequest', - traces: List['Trace'], - timeout: 'ClientTimeout') -> ResponseHandler: - try: - with CeilTimeout(timeout.sock_connect): - _, proto = await self._loop.create_pipe_connection( # type: ignore # noqa - self._factory, self._path - ) - # the drain is required so that the connection_made is called - # and transport is set otherwise it is not set before the - # `assert conn.transport is not None` - # in client.py's _request method - await asyncio.sleep(0) - # other option is to manually set transport like - # `proto.transport = trans` - except OSError as exc: - raise ClientConnectorError(req.connection_key, exc) from exc - - return cast(ResponseHandler, proto) + @asyncio.coroutine + def _create_connection(self, req): + return (yield from self._loop.create_unix_connection( + self._factory, self._path)) diff --git a/venv/Lib/site-packages/aiohttp/cookiejar.py b/venv/Lib/site-packages/aiohttp/cookiejar.py index 160fa227..907b0ca5 100644 --- a/venv/Lib/site-packages/aiohttp/cookiejar.py +++ b/venv/Lib/site-packages/aiohttp/cookiejar.py @@ -1,90 +1,57 @@ -import asyncio import datetime -import os # noqa -import pathlib -import pickle import re from collections import defaultdict -from http.cookies import BaseCookie, Morsel, SimpleCookie # noqa -from typing import ( # noqa - DefaultDict, - Dict, - Iterable, - Iterator, - Mapping, - Optional, - Set, - Tuple, - Union, - cast, -) - -from yarl import URL +from collections.abc import Mapping +from http.cookies import Morsel, SimpleCookie +from math import ceil +from urllib.parse import urlsplit from .abc import AbstractCookieJar -from .helpers import is_ip_address, next_whole_second -from .typedefs import LooseCookies, PathLike - -__all__ = ('CookieJar', 'DummyCookieJar') - - -CookieItem = Union[str, 'Morsel[str]'] +from .helpers import is_ip_address class CookieJar(AbstractCookieJar): """Implements cookie storage adhering to RFC 6265.""" DATE_TOKENS_RE = re.compile( - r"[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]*" - r"(?P[\x00-\x08\x0A-\x1F\d:a-zA-Z\x7F-\xFF]+)") + "[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]*" + "(?P[\x00-\x08\x0A-\x1F\d:a-zA-Z\x7F-\xFF]+)") - DATE_HMS_TIME_RE = re.compile(r"(\d{1,2}):(\d{1,2}):(\d{1,2})") + DATE_HMS_TIME_RE = re.compile("(\d{1,2}):(\d{1,2}):(\d{1,2})") - DATE_DAY_OF_MONTH_RE = re.compile(r"(\d{1,2})") + DATE_DAY_OF_MONTH_RE = re.compile("(\d{1,2})") DATE_MONTH_RE = re.compile("(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|" "(aug)|(sep)|(oct)|(nov)|(dec)", re.I) - DATE_YEAR_RE = re.compile(r"(\d{2,4})") + DATE_YEAR_RE = re.compile("(\d{2,4})") - MAX_TIME = datetime.datetime.max.replace( - tzinfo=datetime.timezone.utc) + MAX_TIME = 2051215261.0 # so far in future (2035-01-01) - def __init__(self, *, unsafe: bool=False, - loop: Optional[asyncio.AbstractEventLoop]=None) -> None: + def __init__(self, *, unsafe=False, loop=None): super().__init__(loop=loop) - self._cookies = defaultdict(SimpleCookie) #type: DefaultDict[str, SimpleCookie] # noqa - self._host_only_cookies = set() # type: Set[Tuple[str, str]] + self._cookies = defaultdict(SimpleCookie) + self._host_only_cookies = set() self._unsafe = unsafe - self._next_expiration = next_whole_second() - self._expirations = {} # type: Dict[Tuple[str, str], datetime.datetime] # noqa: E501 - - def save(self, file_path: PathLike) -> None: - file_path = pathlib.Path(file_path) - with file_path.open(mode='wb') as f: - pickle.dump(self._cookies, f, pickle.HIGHEST_PROTOCOL) - - def load(self, file_path: PathLike) -> None: - file_path = pathlib.Path(file_path) - with file_path.open(mode='rb') as f: - self._cookies = pickle.load(f) + self._next_expiration = ceil(self._loop.time()) + self._expirations = {} - def clear(self) -> None: + def clear(self): self._cookies.clear() self._host_only_cookies.clear() - self._next_expiration = next_whole_second() + self._next_expiration = ceil(self._loop.time()) self._expirations.clear() - def __iter__(self) -> 'Iterator[Morsel[str]]': + def __iter__(self): self._do_expiration() for val in self._cookies.values(): yield from val.values() - def __len__(self) -> int: + def __len__(self): return sum(1 for i in self) - def _do_expiration(self) -> None: - now = datetime.datetime.now(datetime.timezone.utc) + def _do_expiration(self): + now = self._loop.time() if self._next_expiration > now: return if not self._expirations: @@ -94,7 +61,7 @@ class CookieJar(AbstractCookieJar): cookies = self._cookies expirations = self._expirations for (domain, name), when in expirations.items(): - if when <= now: + if when < now: cookies[domain].pop(name, None) to_del.append((domain, name)) self._host_only_cookies.discard((domain, name)) @@ -103,34 +70,28 @@ class CookieJar(AbstractCookieJar): for key in to_del: del expirations[key] - try: - self._next_expiration = (next_expiration.replace(microsecond=0) + - datetime.timedelta(seconds=1)) - except OverflowError: - self._next_expiration = self.MAX_TIME + self._next_expiration = ceil(next_expiration) - def _expire_cookie(self, when: datetime.datetime, domain: str, name: str - ) -> None: + def _expire_cookie(self, when, domain, name): self._next_expiration = min(self._next_expiration, when) self._expirations[(domain, name)] = when - def update_cookies(self, - cookies: LooseCookies, - response_url: URL=URL()) -> None: + def update_cookies(self, cookies, response_url=None): """Update cookies.""" - hostname = response_url.raw_host + url_parsed = urlsplit(response_url or "") + hostname = url_parsed.hostname if not self._unsafe and is_ip_address(hostname): # Don't accept cookies from IPs return if isinstance(cookies, Mapping): - cookies = cookies.items() # type: ignore + cookies = cookies.items() for name, cookie in cookies: if not isinstance(cookie, Morsel): tmp = SimpleCookie() - tmp[name] = cookie # type: ignore + tmp[name] = cookie cookie = tmp[name] domain = cookie["domain"] @@ -158,7 +119,7 @@ class CookieJar(AbstractCookieJar): path = cookie["path"] if not path or not path.startswith("/"): # Set the cookie's path to the response path - path = response_url.path + path = url_parsed.path if not path.startswith("/"): path = "/" else: @@ -170,13 +131,7 @@ class CookieJar(AbstractCookieJar): if max_age: try: delta_seconds = int(max_age) - try: - max_age_expiration = ( - datetime.datetime.now(datetime.timezone.utc) + - datetime.timedelta(seconds=delta_seconds)) - except OverflowError: - max_age_expiration = self.MAX_TIME - self._expire_cookie(max_age_expiration, + self._expire_cookie(self._loop.time() + delta_seconds, domain, name) except ValueError: cookie["max-age"] = "" @@ -186,22 +141,24 @@ class CookieJar(AbstractCookieJar): if expires: expire_time = self._parse_date(expires) if expire_time: - self._expire_cookie(expire_time, + self._expire_cookie(expire_time.timestamp(), domain, name) else: cookie["expires"] = "" - self._cookies[domain][name] = cookie + # use dict method because SimpleCookie class modifies value + # before Python 3.4.3 + dict.__setitem__(self._cookies[domain], name, cookie) self._do_expiration() - def filter_cookies(self, request_url: URL=URL()) -> 'BaseCookie[str]': + def filter_cookies(self, request_url): """Returns this jar's cookies filtered by their attributes.""" self._do_expiration() - request_url = URL(request_url) + url_parsed = urlsplit(request_url) filtered = SimpleCookie() - hostname = request_url.raw_host or "" - is_not_secure = request_url.scheme not in ("https", "wss") + hostname = url_parsed.hostname or "" + is_not_secure = url_parsed.scheme not in ("https", "wss") for cookie in self: name = cookie.key @@ -221,22 +178,18 @@ class CookieJar(AbstractCookieJar): elif not self._is_domain_match(domain, hostname): continue - if not self._is_path_match(request_url.path, cookie["path"]): + if not self._is_path_match(url_parsed.path, cookie["path"]): continue if is_not_secure and cookie["secure"]: continue - # It's critical we use the Morsel so the coded_value - # (based on cookie version) is preserved - mrsl_val = cast('Morsel[str]', cookie.get(cookie.key, Morsel())) - mrsl_val.set(cookie.key, cookie.value, cookie.coded_value) - filtered[name] = mrsl_val + filtered[name] = cookie.value return filtered @staticmethod - def _is_domain_match(domain: str, hostname: str) -> bool: + def _is_domain_match(domain, hostname): """Implements domain matching adhering to RFC 6265.""" if hostname == domain: return True @@ -252,7 +205,7 @@ class CookieJar(AbstractCookieJar): return not is_ip_address(hostname) @staticmethod - def _is_path_match(req_path: str, cookie_path: str) -> bool: + def _is_path_match(req_path, cookie_path): """Implements path matching adhering to RFC 6265.""" if not req_path.startswith("/"): req_path = "/" @@ -271,10 +224,10 @@ class CookieJar(AbstractCookieJar): return non_matching.startswith("/") @classmethod - def _parse_date(cls, date_str: str) -> Optional[datetime.datetime]: + def _parse_date(cls, date_str): """Implements date string parsing adhering to RFC 6265.""" if not date_str: - return None + return found_time = False found_day = False @@ -309,7 +262,6 @@ class CookieJar(AbstractCookieJar): month_match = cls.DATE_MONTH_RE.match(token) if month_match: found_month = True - assert month_match.lastindex is not None month = month_match.lastindex continue @@ -325,44 +277,14 @@ class CookieJar(AbstractCookieJar): year += 2000 if False in (found_day, found_month, found_year, found_time): - return None + return if not 1 <= day <= 31: - return None + return if year < 1601 or hour > 23 or minute > 59 or second > 59: - return None + return return datetime.datetime(year, month, day, hour, minute, second, tzinfo=datetime.timezone.utc) - - -class DummyCookieJar(AbstractCookieJar): - """Implements a dummy cookie storage. - - It can be used with the ClientSession when no cookie processing is needed. - - """ - - def __init__(self, *, - loop: Optional[asyncio.AbstractEventLoop]=None) -> None: - super().__init__(loop=loop) - - def __iter__(self) -> 'Iterator[Morsel[str]]': - while False: - yield None - - def __len__(self) -> int: - return 0 - - def clear(self) -> None: - pass - - def update_cookies(self, - cookies: LooseCookies, - response_url: URL=URL()) -> None: - pass - - def filter_cookies(self, request_url: URL) -> 'BaseCookie[str]': - return SimpleCookie() diff --git a/venv/Lib/site-packages/aiohttp/errors.py b/venv/Lib/site-packages/aiohttp/errors.py new file mode 100644 index 00000000..35f848e0 --- /dev/null +++ b/venv/Lib/site-packages/aiohttp/errors.py @@ -0,0 +1,186 @@ +"""HTTP related errors.""" + +from asyncio import TimeoutError + +__all__ = ( + 'DisconnectedError', 'ClientDisconnectedError', 'ServerDisconnectedError', + + 'HttpProcessingError', 'BadHttpMessage', + 'HttpMethodNotAllowed', 'HttpBadRequest', 'HttpProxyError', + 'BadStatusLine', 'LineTooLong', 'InvalidHeader', + + 'ClientError', 'ClientHttpProcessingError', 'ClientConnectionError', + 'ClientOSError', 'ClientTimeoutError', 'ProxyConnectionError', + 'ClientRequestError', 'ClientResponseError', + 'FingerprintMismatch', + + 'WSServerHandshakeError', 'WSClientDisconnectedError') + + +class DisconnectedError(Exception): + """Disconnected.""" + + +class ClientDisconnectedError(DisconnectedError): + """Client disconnected.""" + + +class ServerDisconnectedError(DisconnectedError): + """Server disconnected.""" + + +class WSClientDisconnectedError(ClientDisconnectedError): + """Deprecated.""" + + +class ClientError(Exception): + """Base class for client connection errors.""" + + +class ClientHttpProcessingError(ClientError): + """Base class for client HTTP processing errors.""" + + +class ClientRequestError(ClientHttpProcessingError): + """Connection error during sending request.""" + + +class ClientResponseError(ClientHttpProcessingError): + """Connection error during reading response.""" + + +class ClientConnectionError(ClientError): + """Base class for client socket errors.""" + + +class ClientOSError(ClientConnectionError, OSError): + """OSError error.""" + + +class ClientTimeoutError(ClientConnectionError, TimeoutError): + """Client connection timeout error.""" + + +class ProxyConnectionError(ClientConnectionError): + """Proxy connection error. + + Raised in :class:`aiohttp.connector.ProxyConnector` if + connection to proxy can not be established. + """ + + +class HttpProcessingError(Exception): + """HTTP error. + + Shortcut for raising HTTP errors with custom code, message and headers. + + :param int code: HTTP Error code. + :param str message: (optional) Error message. + :param list of [tuple] headers: (optional) Headers to be sent in response. + """ + + code = 0 + message = '' + headers = None + + def __init__(self, *, code=None, message='', headers=None): + if code is not None: + self.code = code + self.headers = headers + self.message = message + + super().__init__("%s, message='%s'" % (self.code, message)) + + +class WSServerHandshakeError(HttpProcessingError): + """websocket server handshake error.""" + + +class HttpProxyError(HttpProcessingError): + """HTTP proxy error. + + Raised in :class:`aiohttp.connector.ProxyConnector` if + proxy responds with status other than ``200 OK`` + on ``CONNECT`` request. + """ + + +class BadHttpMessage(HttpProcessingError): + + code = 400 + message = 'Bad Request' + + def __init__(self, message, *, headers=None): + super().__init__(message=message, headers=headers) + + +class HttpMethodNotAllowed(HttpProcessingError): + + code = 405 + message = 'Method Not Allowed' + + +class HttpBadRequest(BadHttpMessage): + + code = 400 + message = 'Bad Request' + + +class ContentEncodingError(BadHttpMessage): + """Content encoding error.""" + + +class TransferEncodingError(BadHttpMessage): + """transfer encoding error.""" + + +class LineTooLong(BadHttpMessage): + + def __init__(self, line, limit='Unknown'): + super().__init__( + "got more than %s bytes when reading %s" % (limit, line)) + + +class InvalidHeader(BadHttpMessage): + + def __init__(self, hdr): + if isinstance(hdr, bytes): + hdr = hdr.decode('utf-8', 'surrogateescape') + super().__init__('Invalid HTTP Header: {}'.format(hdr)) + self.hdr = hdr + + +class BadStatusLine(BadHttpMessage): + + def __init__(self, line=''): + if not line: + line = repr(line) + self.args = line, + self.line = line + + +class LineLimitExceededParserError(HttpBadRequest): + """Line is too long.""" + + def __init__(self, msg, limit): + super().__init__(msg) + self.limit = limit + + +class FingerprintMismatch(ClientConnectionError): + """SSL certificate does not match expected fingerprint.""" + + def __init__(self, expected, got, host, port): + self.expected = expected + self.got = got + self.host = host + self.port = port + + def __repr__(self): + return '<{} expected={} got={} host={} port={}>'.format( + self.__class__.__name__, self.expected, self.got, + self.host, self.port) + + +class InvalidURL(Exception): + """Invalid URL.""" diff --git a/venv/Lib/site-packages/aiohttp/formdata.py b/venv/Lib/site-packages/aiohttp/formdata.py deleted file mode 100644 index b4ffa048..00000000 --- a/venv/Lib/site-packages/aiohttp/formdata.py +++ /dev/null @@ -1,150 +0,0 @@ -import io -from typing import Any, Iterable, List, Optional # noqa -from urllib.parse import urlencode - -from multidict import MultiDict, MultiDictProxy - -from . import hdrs, multipart, payload -from .helpers import guess_filename -from .payload import Payload - -__all__ = ('FormData',) - - -class FormData: - """Helper class for multipart/form-data and - application/x-www-form-urlencoded body generation.""" - - def __init__(self, fields: - Iterable[Any]=(), - quote_fields: bool=True, - charset: Optional[str]=None) -> None: - self._writer = multipart.MultipartWriter('form-data') - self._fields = [] # type: List[Any] - self._is_multipart = False - self._quote_fields = quote_fields - self._charset = charset - - if isinstance(fields, dict): - fields = list(fields.items()) - elif not isinstance(fields, (list, tuple)): - fields = (fields,) - self.add_fields(*fields) - - @property - def is_multipart(self) -> bool: - return self._is_multipart - - def add_field(self, name: str, value: Any, *, - content_type: Optional[str]=None, - filename: Optional[str]=None, - content_transfer_encoding: Optional[str]=None) -> None: - - if isinstance(value, io.IOBase): - self._is_multipart = True - elif isinstance(value, (bytes, bytearray, memoryview)): - if filename is None and content_transfer_encoding is None: - filename = name - - type_options = MultiDict({'name': name}) - if filename is not None and not isinstance(filename, str): - raise TypeError('filename must be an instance of str. ' - 'Got: %s' % filename) - if filename is None and isinstance(value, io.IOBase): - filename = guess_filename(value, name) - if filename is not None: - type_options['filename'] = filename - self._is_multipart = True - - headers = {} - if content_type is not None: - if not isinstance(content_type, str): - raise TypeError('content_type must be an instance of str. ' - 'Got: %s' % content_type) - headers[hdrs.CONTENT_TYPE] = content_type - self._is_multipart = True - if content_transfer_encoding is not None: - if not isinstance(content_transfer_encoding, str): - raise TypeError('content_transfer_encoding must be an instance' - ' of str. Got: %s' % content_transfer_encoding) - headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding - self._is_multipart = True - - self._fields.append((type_options, headers, value)) - - def add_fields(self, *fields: Any) -> None: - to_add = list(fields) - - while to_add: - rec = to_add.pop(0) - - if isinstance(rec, io.IOBase): - k = guess_filename(rec, 'unknown') - self.add_field(k, rec) # type: ignore - - elif isinstance(rec, (MultiDictProxy, MultiDict)): - to_add.extend(rec.items()) - - elif isinstance(rec, (list, tuple)) and len(rec) == 2: - k, fp = rec - self.add_field(k, fp) # type: ignore - - else: - raise TypeError('Only io.IOBase, multidict and (name, file) ' - 'pairs allowed, use .add_field() for passing ' - 'more complex parameters, got {!r}' - .format(rec)) - - def _gen_form_urlencoded(self) -> payload.BytesPayload: - # form data (x-www-form-urlencoded) - data = [] - for type_options, _, value in self._fields: - data.append((type_options['name'], value)) - - charset = self._charset if self._charset is not None else 'utf-8' - - if charset == 'utf-8': - content_type = 'application/x-www-form-urlencoded' - else: - content_type = ('application/x-www-form-urlencoded; ' - 'charset=%s' % charset) - - return payload.BytesPayload( - urlencode(data, doseq=True, encoding=charset).encode(), - content_type=content_type) - - def _gen_form_data(self) -> multipart.MultipartWriter: - """Encode a list of fields using the multipart/form-data MIME format""" - for dispparams, headers, value in self._fields: - try: - if hdrs.CONTENT_TYPE in headers: - part = payload.get_payload( - value, content_type=headers[hdrs.CONTENT_TYPE], - headers=headers, encoding=self._charset) - else: - part = payload.get_payload( - value, headers=headers, encoding=self._charset) - except Exception as exc: - raise TypeError( - 'Can not serialize value type: %r\n ' - 'headers: %r\n value: %r' % ( - type(value), headers, value)) from exc - - if dispparams: - part.set_content_disposition( - 'form-data', quote_fields=self._quote_fields, **dispparams - ) - # FIXME cgi.FieldStorage doesn't likes body parts with - # Content-Length which were sent via chunked transfer encoding - assert part.headers is not None - part.headers.popall(hdrs.CONTENT_LENGTH, None) - - self._writer.append_payload(part) - - return self._writer - - def __call__(self) -> Payload: - if self._is_multipart: - return self._gen_form_data() - else: - return self._gen_form_urlencoded() diff --git a/venv/Lib/site-packages/aiohttp/frozenlist.py b/venv/Lib/site-packages/aiohttp/frozenlist.py deleted file mode 100644 index 2aaea647..00000000 --- a/venv/Lib/site-packages/aiohttp/frozenlist.py +++ /dev/null @@ -1,72 +0,0 @@ -from collections.abc import MutableSequence -from functools import total_ordering - -from .helpers import NO_EXTENSIONS - - -@total_ordering -class FrozenList(MutableSequence): - - __slots__ = ('_frozen', '_items') - - def __init__(self, items=None): - self._frozen = False - if items is not None: - items = list(items) - else: - items = [] - self._items = items - - @property - def frozen(self): - return self._frozen - - def freeze(self): - self._frozen = True - - def __getitem__(self, index): - return self._items[index] - - def __setitem__(self, index, value): - if self._frozen: - raise RuntimeError("Cannot modify frozen list.") - self._items[index] = value - - def __delitem__(self, index): - if self._frozen: - raise RuntimeError("Cannot modify frozen list.") - del self._items[index] - - def __len__(self): - return self._items.__len__() - - def __iter__(self): - return self._items.__iter__() - - def __reversed__(self): - return self._items.__reversed__() - - def __eq__(self, other): - return list(self) == other - - def __le__(self, other): - return list(self) <= other - - def insert(self, pos, item): - if self._frozen: - raise RuntimeError("Cannot modify frozen list.") - self._items.insert(pos, item) - - def __repr__(self): - return ''.format(self._frozen, - self._items) - - -PyFrozenList = FrozenList - -try: - from aiohttp._frozenlist import FrozenList as CFrozenList # type: ignore - if not NO_EXTENSIONS: - FrozenList = CFrozenList # type: ignore -except ImportError: # pragma: no cover - pass diff --git a/venv/Lib/site-packages/aiohttp/frozenlist.pyi b/venv/Lib/site-packages/aiohttp/frozenlist.pyi deleted file mode 100644 index 81ca25cd..00000000 --- a/venv/Lib/site-packages/aiohttp/frozenlist.pyi +++ /dev/null @@ -1,63 +0,0 @@ -from typing import ( - Generic, - Iterable, - Iterator, - List, - MutableSequence, - Optional, - TypeVar, - Union, - overload, -) - -_T = TypeVar('_T') -_Arg = Union[List[_T], Iterable[_T]] - - -class FrozenList(MutableSequence[_T], Generic[_T]): - - def __init__(self, items: Optional[_Arg[_T]]=...) -> None: ... - - @property - def frozen(self) -> bool: ... - - def freeze(self) -> None: ... - - @overload - def __getitem__(self, i: int) -> _T: ... - - @overload - def __getitem__(self, s: slice) -> FrozenList[_T]: ... - - @overload - def __setitem__(self, i: int, o: _T) -> None: ... - - @overload - def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... - - @overload - def __delitem__(self, i: int) -> None: ... - - @overload - def __delitem__(self, i: slice) -> None: ... - - def __len__(self) -> int: ... - - def __iter__(self) -> Iterator[_T]: ... - - def __reversed__(self) -> Iterator[_T]: ... - - def __eq__(self, other: object) -> bool: ... - def __le__(self, other: FrozenList[_T]) -> bool: ... - def __ne__(self, other: object) -> bool: ... - def __lt__(self, other: FrozenList[_T]) -> bool: ... - def __ge__(self, other: FrozenList[_T]) -> bool: ... - def __gt__(self, other: FrozenList[_T]) -> bool: ... - - def insert(self, pos: int, item: _T) -> None: ... - - def __repr__(self) -> str: ... - - -# types for C accelerators are the same -CFrozenList = PyFrozenList = FrozenList diff --git a/venv/Lib/site-packages/aiohttp/hdrs.py b/venv/Lib/site-packages/aiohttp/hdrs.py index c11a9d30..f994319e 100644 --- a/venv/Lib/site-packages/aiohttp/hdrs.py +++ b/venv/Lib/site-packages/aiohttp/hdrs.py @@ -1,8 +1,4 @@ """HTTP Headers constants.""" - -# After changing the file content call ./tools/gen.py -# to regenerate the headers parser - from multidict import istr METH_ANY = '*' @@ -20,81 +16,76 @@ METH_ALL = {METH_CONNECT, METH_HEAD, METH_GET, METH_DELETE, METH_OPTIONS, METH_PATCH, METH_POST, METH_PUT, METH_TRACE} -ACCEPT = istr('Accept') -ACCEPT_CHARSET = istr('Accept-Charset') -ACCEPT_ENCODING = istr('Accept-Encoding') -ACCEPT_LANGUAGE = istr('Accept-Language') -ACCEPT_RANGES = istr('Accept-Ranges') -ACCESS_CONTROL_MAX_AGE = istr('Access-Control-Max-Age') -ACCESS_CONTROL_ALLOW_CREDENTIALS = istr('Access-Control-Allow-Credentials') -ACCESS_CONTROL_ALLOW_HEADERS = istr('Access-Control-Allow-Headers') -ACCESS_CONTROL_ALLOW_METHODS = istr('Access-Control-Allow-Methods') -ACCESS_CONTROL_ALLOW_ORIGIN = istr('Access-Control-Allow-Origin') -ACCESS_CONTROL_EXPOSE_HEADERS = istr('Access-Control-Expose-Headers') -ACCESS_CONTROL_REQUEST_HEADERS = istr('Access-Control-Request-Headers') -ACCESS_CONTROL_REQUEST_METHOD = istr('Access-Control-Request-Method') -AGE = istr('Age') -ALLOW = istr('Allow') -AUTHORIZATION = istr('Authorization') -CACHE_CONTROL = istr('Cache-Control') -CONNECTION = istr('Connection') -CONTENT_DISPOSITION = istr('Content-Disposition') -CONTENT_ENCODING = istr('Content-Encoding') -CONTENT_LANGUAGE = istr('Content-Language') -CONTENT_LENGTH = istr('Content-Length') -CONTENT_LOCATION = istr('Content-Location') -CONTENT_MD5 = istr('Content-MD5') -CONTENT_RANGE = istr('Content-Range') -CONTENT_TRANSFER_ENCODING = istr('Content-Transfer-Encoding') -CONTENT_TYPE = istr('Content-Type') -COOKIE = istr('Cookie') -DATE = istr('Date') -DESTINATION = istr('Destination') -DIGEST = istr('Digest') -ETAG = istr('Etag') -EXPECT = istr('Expect') -EXPIRES = istr('Expires') -FORWARDED = istr('Forwarded') -FROM = istr('From') -HOST = istr('Host') -IF_MATCH = istr('If-Match') -IF_MODIFIED_SINCE = istr('If-Modified-Since') -IF_NONE_MATCH = istr('If-None-Match') -IF_RANGE = istr('If-Range') -IF_UNMODIFIED_SINCE = istr('If-Unmodified-Since') -KEEP_ALIVE = istr('Keep-Alive') -LAST_EVENT_ID = istr('Last-Event-ID') -LAST_MODIFIED = istr('Last-Modified') -LINK = istr('Link') -LOCATION = istr('Location') -MAX_FORWARDS = istr('Max-Forwards') -ORIGIN = istr('Origin') -PRAGMA = istr('Pragma') -PROXY_AUTHENTICATE = istr('Proxy-Authenticate') -PROXY_AUTHORIZATION = istr('Proxy-Authorization') -RANGE = istr('Range') -REFERER = istr('Referer') -RETRY_AFTER = istr('Retry-After') -SEC_WEBSOCKET_ACCEPT = istr('Sec-WebSocket-Accept') -SEC_WEBSOCKET_VERSION = istr('Sec-WebSocket-Version') -SEC_WEBSOCKET_PROTOCOL = istr('Sec-WebSocket-Protocol') -SEC_WEBSOCKET_EXTENSIONS = istr('Sec-WebSocket-Extensions') -SEC_WEBSOCKET_KEY = istr('Sec-WebSocket-Key') -SEC_WEBSOCKET_KEY1 = istr('Sec-WebSocket-Key1') -SERVER = istr('Server') -SET_COOKIE = istr('Set-Cookie') +ACCEPT = istr('ACCEPT') +ACCEPT_CHARSET = istr('ACCEPT-CHARSET') +ACCEPT_ENCODING = istr('ACCEPT-ENCODING') +ACCEPT_LANGUAGE = istr('ACCEPT-LANGUAGE') +ACCEPT_RANGES = istr('ACCEPT-RANGES') +ACCESS_CONTROL_MAX_AGE = istr('ACCESS-CONTROL-MAX-AGE') +ACCESS_CONTROL_ALLOW_CREDENTIALS = istr('ACCESS-CONTROL-ALLOW-CREDENTIALS') +ACCESS_CONTROL_ALLOW_HEADERS = istr('ACCESS-CONTROL-ALLOW-HEADERS') +ACCESS_CONTROL_ALLOW_METHODS = istr('ACCESS-CONTROL-ALLOW-METHODS') +ACCESS_CONTROL_ALLOW_ORIGIN = istr('ACCESS-CONTROL-ALLOW-ORIGIN') +ACCESS_CONTROL_EXPOSE_HEADERS = istr('ACCESS-CONTROL-EXPOSE-HEADERS') +ACCESS_CONTROL_REQUEST_HEADERS = istr('ACCESS-CONTROL-REQUEST-HEADERS') +ACCESS_CONTROL_REQUEST_METHOD = istr('ACCESS-CONTROL-REQUEST-METHOD') +AGE = istr('AGE') +ALLOW = istr('ALLOW') +AUTHORIZATION = istr('AUTHORIZATION') +CACHE_CONTROL = istr('CACHE-CONTROL') +CONNECTION = istr('CONNECTION') +CONTENT_DISPOSITION = istr('CONTENT-DISPOSITION') +CONTENT_ENCODING = istr('CONTENT-ENCODING') +CONTENT_LANGUAGE = istr('CONTENT-LANGUAGE') +CONTENT_LENGTH = istr('CONTENT-LENGTH') +CONTENT_LOCATION = istr('CONTENT-LOCATION') +CONTENT_MD5 = istr('CONTENT-MD5') +CONTENT_RANGE = istr('CONTENT-RANGE') +CONTENT_TRANSFER_ENCODING = istr('CONTENT-TRANSFER-ENCODING') +CONTENT_TYPE = istr('CONTENT-TYPE') +COOKIE = istr('COOKIE') +DATE = istr('DATE') +DESTINATION = istr('DESTINATION') +DIGEST = istr('DIGEST') +ETAG = istr('ETAG') +EXPECT = istr('EXPECT') +EXPIRES = istr('EXPIRES') +FROM = istr('FROM') +HOST = istr('HOST') +IF_MATCH = istr('IF-MATCH') +IF_MODIFIED_SINCE = istr('IF-MODIFIED-SINCE') +IF_NONE_MATCH = istr('IF-NONE-MATCH') +IF_RANGE = istr('IF-RANGE') +IF_UNMODIFIED_SINCE = istr('IF-UNMODIFIED-SINCE') +KEEP_ALIVE = istr('KEEP-ALIVE') +LAST_EVENT_ID = istr('LAST-EVENT-ID') +LAST_MODIFIED = istr('LAST-MODIFIED') +LINK = istr('LINK') +LOCATION = istr('LOCATION') +MAX_FORWARDS = istr('MAX-FORWARDS') +ORIGIN = istr('ORIGIN') +PRAGMA = istr('PRAGMA') +PROXY_AUTHENTICATE = istr('PROXY_AUTHENTICATE') +PROXY_AUTHORIZATION = istr('PROXY-AUTHORIZATION') +RANGE = istr('RANGE') +REFERER = istr('REFERER') +RETRY_AFTER = istr('RETRY-AFTER') +SEC_WEBSOCKET_ACCEPT = istr('SEC-WEBSOCKET-ACCEPT') +SEC_WEBSOCKET_VERSION = istr('SEC-WEBSOCKET-VERSION') +SEC_WEBSOCKET_PROTOCOL = istr('SEC-WEBSOCKET-PROTOCOL') +SEC_WEBSOCKET_KEY = istr('SEC-WEBSOCKET-KEY') +SEC_WEBSOCKET_KEY1 = istr('SEC-WEBSOCKET-KEY1') +SERVER = istr('SERVER') +SET_COOKIE = istr('SET-COOKIE') TE = istr('TE') -TRAILER = istr('Trailer') -TRANSFER_ENCODING = istr('Transfer-Encoding') -UPGRADE = istr('Upgrade') -WEBSOCKET = istr('WebSocket') +TRAILER = istr('TRAILER') +TRANSFER_ENCODING = istr('TRANSFER-ENCODING') +UPGRADE = istr('UPGRADE') +WEBSOCKET = istr('WEBSOCKET') URI = istr('URI') -USER_AGENT = istr('User-Agent') -VARY = istr('Vary') -VIA = istr('Via') -WANT_DIGEST = istr('Want-Digest') -WARNING = istr('Warning') -WWW_AUTHENTICATE = istr('WWW-Authenticate') -X_FORWARDED_FOR = istr('X-Forwarded-For') -X_FORWARDED_HOST = istr('X-Forwarded-Host') -X_FORWARDED_PROTO = istr('X-Forwarded-Proto') +USER_AGENT = istr('USER-AGENT') +VARY = istr('VARY') +VIA = istr('VIA') +WANT_DIGEST = istr('WANT-DIGEST') +WARNING = istr('WARNING') +WWW_AUTHENTICATE = istr('WWW-AUTHENTICATE') diff --git a/venv/Lib/site-packages/aiohttp/helpers.py b/venv/Lib/site-packages/aiohttp/helpers.py index 5277f525..5b3f524e 100644 --- a/venv/Lib/site-packages/aiohttp/helpers.py +++ b/venv/Lib/site-packages/aiohttp/helpers.py @@ -3,372 +3,410 @@ import asyncio import base64 import binascii -import cgi import datetime import functools -import inspect -import netrc +import io import os -import platform import re -import sys -import time import warnings -import weakref from collections import namedtuple -from contextlib import suppress -from math import ceil from pathlib import Path -from types import TracebackType -from typing import ( # noqa - Any, - Callable, - Dict, - Iterable, - Iterator, - List, - Mapping, - Optional, - Pattern, - Set, - Tuple, - Type, - TypeVar, - Union, - cast, -) -from urllib.parse import quote -from urllib.request import getproxies - -import async_timeout -import attr +from urllib.parse import quote, urlencode + +from async_timeout import timeout from multidict import MultiDict, MultiDictProxy -from yarl import URL from . import hdrs -from .log import client_logger, internal_logger -from .typedefs import PathLike # noqa - -__all__ = ('BasicAuth', 'ChainMapProxy') - -PY_36 = sys.version_info >= (3, 6) -PY_37 = sys.version_info >= (3, 7) -PY_38 = sys.version_info >= (3, 8) - -if not PY_37: - import idna_ssl - idna_ssl.patch_match_hostname() +from .errors import InvalidURL try: - from typing import ContextManager + from asyncio import ensure_future except ImportError: - from typing_extensions import ContextManager - - -def all_tasks( - loop: Optional[asyncio.AbstractEventLoop] = None -) -> Set['asyncio.Task[Any]']: - tasks = list(asyncio.Task.all_tasks(loop)) - return {t for t in tasks if not t.done()} - - -if PY_37: - all_tasks = getattr(asyncio, 'all_tasks') # noqa - - -_T = TypeVar('_T') - - -sentinel = object() # type: Any -NO_EXTENSIONS = bool(os.environ.get('AIOHTTP_NO_EXTENSIONS')) # type: bool - -# N.B. sys.flags.dev_mode is available on Python 3.7+, use getattr -# for compatibility with older versions -DEBUG = (getattr(sys.flags, 'dev_mode', False) or - (not sys.flags.ignore_environment and - bool(os.environ.get('PYTHONASYNCIODEBUG')))) # type: bool - - -CHAR = set(chr(i) for i in range(0, 128)) -CTL = set(chr(i) for i in range(0, 32)) | {chr(127), } -SEPARATORS = {'(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', - '?', '=', '{', '}', ' ', chr(9)} -TOKEN = CHAR ^ CTL ^ SEPARATORS - - -coroutines = asyncio.coroutines -old_debug = coroutines._DEBUG # type: ignore + ensure_future = asyncio.async -# prevent "coroutine noop was never awaited" warning. -coroutines._DEBUG = False # type: ignore +__all__ = ('BasicAuth', 'create_future', 'FormData', 'parse_mimetype', + 'Timeout', 'ensure_future') -@asyncio.coroutine -def noop(*args, **kwargs): # type: ignore - return # type: ignore - -async def noop2(*args: Any, **kwargs: Any) -> None: - return - - -coroutines._DEBUG = old_debug # type: ignore +sentinel = object() +Timeout = timeout class BasicAuth(namedtuple('BasicAuth', ['login', 'password', 'encoding'])): - """Http basic authentication helper.""" + """Http basic authentication helper. + + :param str login: Login + :param str password: Password + :param str encoding: (optional) encoding ('latin1' by default) + """ - def __new__(cls, login: str, - password: str='', - encoding: str='latin1') -> 'BasicAuth': + def __new__(cls, login, password='', encoding='latin1'): if login is None: raise ValueError('None is not allowed as login value') if password is None: raise ValueError('None is not allowed as password value') - if ':' in login: - raise ValueError( - 'A ":" is not allowed in login (RFC 1945#section-11.1)') - return super().__new__(cls, login, password, encoding) @classmethod - def decode(cls, auth_header: str, encoding: str='latin1') -> 'BasicAuth': - """Create a BasicAuth object from an Authorization HTTP header.""" - try: - auth_type, encoded_credentials = auth_header.split(' ', 1) - except ValueError: + def decode(cls, auth_header, encoding='latin1'): + """Create a :class:`BasicAuth` object from an ``Authorization`` HTTP + header.""" + split = auth_header.strip().split(' ') + if len(split) == 2: + if split[0].strip().lower() != 'basic': + raise ValueError('Unknown authorization method %s' % split[0]) + to_decode = split[1] + else: raise ValueError('Could not parse authorization header.') - if auth_type.lower() != 'basic': - raise ValueError('Unknown authorization method %s' % auth_type) - try: - decoded = base64.b64decode( - encoded_credentials.encode('ascii'), validate=True - ).decode(encoding) + username, _, password = base64.b64decode( + to_decode.encode('ascii') + ).decode(encoding).partition(':') except binascii.Error: raise ValueError('Invalid base64 encoding.') - try: - # RFC 2617 HTTP Authentication - # https://www.ietf.org/rfc/rfc2617.txt - # the colon must be present, but the username and password may be - # otherwise blank. - username, password = decoded.split(':', 1) - except ValueError: - raise ValueError('Invalid credentials.') - return cls(username, password, encoding=encoding) - @classmethod - def from_url(cls, url: URL, - *, encoding: str='latin1') -> Optional['BasicAuth']: - """Create BasicAuth from url.""" - if not isinstance(url, URL): - raise TypeError("url should be yarl.URL instance") - if url.user is None: - return None - return cls(url.user, url.password or '', encoding=encoding) - - def encode(self) -> str: + def encode(self): """Encode credentials.""" creds = ('%s:%s' % (self.login, self.password)).encode(self.encoding) return 'Basic %s' % base64.b64encode(creds).decode(self.encoding) -def strip_auth_from_url(url: URL) -> Tuple[URL, Optional[BasicAuth]]: - auth = BasicAuth.from_url(url) - if auth is None: - return url, None +def create_future(loop): + """Compatibility wrapper for the loop.create_future() call introduced in + 3.5.2.""" + if hasattr(loop, 'create_future'): + return loop.create_future() else: - return url.with_user(None), auth - + return asyncio.Future(loop=loop) -def netrc_from_env() -> Optional[netrc.netrc]: - """Attempt to load the netrc file from the path specified by the env-var - NETRC or in the default location in the user's home directory. - Returns None if it couldn't be found or fails to parse. - """ - netrc_env = os.environ.get('NETRC') - - if netrc_env is not None: - netrc_path = Path(netrc_env) - else: - try: - home_dir = Path.home() - except RuntimeError as e: # pragma: no cover - # if pathlib can't resolve home, it may raise a RuntimeError - client_logger.debug('Could not resolve home directory when ' - 'trying to look for .netrc file: %s', e) - return None +class FormData: + """Helper class for multipart/form-data and + application/x-www-form-urlencoded body generation.""" - netrc_path = home_dir / ( - '_netrc' if platform.system() == 'Windows' else '.netrc') + def __init__(self, fields=()): + from . import multipart + self._writer = multipart.MultipartWriter('form-data') + self._fields = [] + self._is_multipart = False - try: - return netrc.netrc(str(netrc_path)) - except netrc.NetrcParseError as e: - client_logger.warning('Could not parse .netrc file: %s', e) - except OSError as e: - # we couldn't read the file (doesn't exist, permissions, etc.) - if netrc_env or netrc_path.is_file(): - # only warn if the environment wanted us to load it, - # or it appears like the default file does actually exist - client_logger.warning('Could not read .netrc file: %s', e) - - return None - - -@attr.s(frozen=True, slots=True) -class ProxyInfo: - proxy = attr.ib(type=URL) - proxy_auth = attr.ib(type=Optional[BasicAuth]) - - -def proxies_from_env() -> Dict[str, ProxyInfo]: - proxy_urls = {k: URL(v) for k, v in getproxies().items() - if k in ('http', 'https')} - netrc_obj = netrc_from_env() - stripped = {k: strip_auth_from_url(v) for k, v in proxy_urls.items()} - ret = {} - for proto, val in stripped.items(): - proxy, auth = val - if proxy.scheme == 'https': - client_logger.warning( - "HTTPS proxies %s are not supported, ignoring", proxy) - continue - if netrc_obj and auth is None: - auth_from_netrc = None - if proxy.host is not None: - auth_from_netrc = netrc_obj.authenticators(proxy.host) - if auth_from_netrc is not None: - # auth_from_netrc is a (`user`, `account`, `password`) tuple, - # `user` and `account` both can be username, - # if `user` is None, use `account` - *logins, password = auth_from_netrc - login = logins[0] if logins[0] else logins[-1] - auth = BasicAuth(cast(str, login), cast(str, password)) - ret[proto] = ProxyInfo(proxy, auth) - return ret - - -def current_task(loop: Optional[asyncio.AbstractEventLoop]=None) -> asyncio.Task: # type: ignore # noqa # Return type is intentionally Generic here - if PY_37: - return asyncio.current_task(loop=loop) # type: ignore - else: - return asyncio.Task.current_task(loop=loop) - - -def get_running_loop( - loop: Optional[asyncio.AbstractEventLoop]=None -) -> asyncio.AbstractEventLoop: - if loop is None: - loop = asyncio.get_event_loop() - if not loop.is_running(): - warnings.warn("The object should be created from async function", - DeprecationWarning, stacklevel=3) - if loop.get_debug(): - internal_logger.warning( - "The object should be created from async function", - stack_info=True) - return loop - - -def isasyncgenfunction(obj: Any) -> bool: - func = getattr(inspect, 'isasyncgenfunction', None) - if func is not None: - return func(obj) - else: - return False + if isinstance(fields, dict): + fields = list(fields.items()) + elif not isinstance(fields, (list, tuple)): + fields = (fields,) + self.add_fields(*fields) + @property + def is_multipart(self): + return self._is_multipart -@attr.s(frozen=True, slots=True) -class MimeType: - type = attr.ib(type=str) - subtype = attr.ib(type=str) - suffix = attr.ib(type=str) - parameters = attr.ib(type=MultiDictProxy) # type: MultiDictProxy[str] + @property + def content_type(self): + if self._is_multipart: + return self._writer.headers[hdrs.CONTENT_TYPE] + else: + return 'application/x-www-form-urlencoded' + + def add_field(self, name, value, *, content_type=None, filename=None, + content_transfer_encoding=None): + + if isinstance(value, io.IOBase): + self._is_multipart = True + elif isinstance(value, (bytes, bytearray, memoryview)): + if filename is None and content_transfer_encoding is None: + filename = name + + type_options = MultiDict({'name': name}) + if filename is not None and not isinstance(filename, str): + raise TypeError('filename must be an instance of str. ' + 'Got: %s' % filename) + if filename is None and isinstance(value, io.IOBase): + filename = guess_filename(value, name) + if filename is not None: + type_options['filename'] = filename + self._is_multipart = True + + headers = {} + if content_type is not None: + if not isinstance(content_type, str): + raise TypeError('content_type must be an instance of str. ' + 'Got: %s' % content_type) + headers[hdrs.CONTENT_TYPE] = content_type + self._is_multipart = True + if content_transfer_encoding is not None: + if not isinstance(content_transfer_encoding, str): + raise TypeError('content_transfer_encoding must be an instance' + ' of str. Got: %s' % content_transfer_encoding) + headers[hdrs.CONTENT_TRANSFER_ENCODING] = content_transfer_encoding + self._is_multipart = True + + self._fields.append((type_options, headers, value)) + + def add_fields(self, *fields): + to_add = list(fields) + + while to_add: + rec = to_add.pop(0) + + if isinstance(rec, io.IOBase): + k = guess_filename(rec, 'unknown') + self.add_field(k, rec) + + elif isinstance(rec, (MultiDictProxy, MultiDict)): + to_add.extend(rec.items()) + + elif isinstance(rec, (list, tuple)) and len(rec) == 2: + k, fp = rec + self.add_field(k, fp) + + else: + raise TypeError('Only io.IOBase, multidict and (name, file) ' + 'pairs allowed, use .add_field() for passing ' + 'more complex parameters') + + def _gen_form_urlencoded(self, encoding): + # form data (x-www-form-urlencoded) + data = [] + for type_options, _, value in self._fields: + data.append((type_options['name'], value)) + + data = urlencode(data, doseq=True) + return data.encode(encoding) + + def _gen_form_data(self, *args, **kwargs): + """Encode a list of fields using the multipart/form-data MIME format""" + for dispparams, headers, value in self._fields: + part = self._writer.append(value, headers) + if dispparams: + part.set_content_disposition('form-data', **dispparams) + # FIXME cgi.FieldStorage doesn't likes body parts with + # Content-Length which were sent via chunked transfer encoding + part.headers.pop(hdrs.CONTENT_LENGTH, None) + yield from self._writer.serialize() + + def __call__(self, encoding): + if self._is_multipart: + return self._gen_form_data(encoding) + else: + return self._gen_form_urlencoded(encoding) -@functools.lru_cache(maxsize=56) -def parse_mimetype(mimetype: str) -> MimeType: +def parse_mimetype(mimetype): """Parses a MIME type into its components. - mimetype is a MIME type string. + :param str mimetype: MIME type - Returns a MimeType object. + :returns: 4 element tuple for MIME type, subtype, suffix and parameters + :rtype: tuple Example: >>> parse_mimetype('text/html; charset=utf-8') - MimeType(type='text', subtype='html', suffix='', - parameters={'charset': 'utf-8'}) + ('text', 'html', '', {'charset': 'utf-8'}) """ if not mimetype: - return MimeType(type='', subtype='', suffix='', - parameters=MultiDictProxy(MultiDict())) + return '', '', '', {} parts = mimetype.split(';') - params = MultiDict() # type: MultiDict[str] + params = [] for item in parts[1:]: if not item: continue - key, value = cast(Tuple[str, str], - item.split('=', 1) if '=' in item else (item, '')) - params.add(key.lower().strip(), value.strip(' "')) + key, value = item.split('=', 1) if '=' in item else (item, '') + params.append((key.lower().strip(), value.strip(' "'))) + params = dict(params) fulltype = parts[0].strip().lower() if fulltype == '*': fulltype = '*/*' - mtype, stype = (cast(Tuple[str, str], fulltype.split('/', 1)) - if '/' in fulltype else (fulltype, '')) - stype, suffix = (cast(Tuple[str, str], stype.split('+', 1)) - if '+' in stype else (stype, '')) + mtype, stype = fulltype.split('/', 1) \ + if '/' in fulltype else (fulltype, '') + stype, suffix = stype.split('+', 1) if '+' in stype else (stype, '') - return MimeType(type=mtype, subtype=stype, suffix=suffix, - parameters=MultiDictProxy(params)) + return mtype, stype, suffix, params -def guess_filename(obj: Any, default: Optional[str]=None) -> Optional[str]: +def guess_filename(obj, default=None): name = getattr(obj, 'name', None) - if name and isinstance(name, str) and name[0] != '<' and name[-1] != '>': + if name and name[0] != '<' and name[-1] != '>': return Path(name).name return default -def content_disposition_header(disptype: str, - quote_fields: bool=True, - **params: str) -> str: - """Sets ``Content-Disposition`` header. +class AccessLogger: + """Helper object to log access. + + Usage: + log = logging.getLogger("spam") + log_format = "%a %{User-Agent}i" + access_logger = AccessLogger(log, log_format) + access_logger.log(message, environ, response, transport, time) + + Format: + %% The percent sign + %a Remote IP-address (IP-address of proxy if using reverse proxy) + %t Time when the request was started to process + %P The process ID of the child that serviced the request + %r First line of request + %s Response status code + %b Size of response in bytes, excluding HTTP headers + %O Bytes sent, including headers + %T Time taken to serve the request, in seconds + %Tf Time taken to serve the request, in seconds with floating fraction + in .06f format + %D Time taken to serve the request, in microseconds + %{FOO}i request.headers['FOO'] + %{FOO}o response.headers['FOO'] + %{FOO}e os.environ['FOO'] - disptype is a disposition type: inline, attachment, form-data. - Should be valid extension token (see RFC 2183) - - params is a dict with disposition params. """ - if not disptype or not (TOKEN > set(disptype)): - raise ValueError('bad content disposition type {!r}' - ''.format(disptype)) - - value = disptype - if params: - lparams = [] - for key, val in params.items(): - if not key or not (TOKEN > set(key)): - raise ValueError('bad content disposition parameter' - ' {!r}={!r}'.format(key, val)) - qval = quote(val, '') if quote_fields else val - lparams.append((key, '"%s"' % qval)) - if key == 'filename': - lparams.append(('filename*', "utf-8''" + qval)) - sparams = '; '.join('='.join(pair) for pair in lparams) - value = '; '.join((value, sparams)) - return value + + LOG_FORMAT = '%a %l %u %t "%r" %s %b "%{Referrer}i" "%{User-Agent}i"' + FORMAT_RE = re.compile(r'%(\{([A-Za-z\-]+)\}([ioe])|[atPrsbOD]|Tf?)') + CLEANUP_RE = re.compile(r'(%[^s])') + _FORMAT_CACHE = {} + + def __init__(self, logger, log_format=LOG_FORMAT): + """Initialise the logger. + + :param logger: logger object to be used for logging + :param log_format: apache compatible log format + + """ + self.logger = logger + _compiled_format = AccessLogger._FORMAT_CACHE.get(log_format) + if not _compiled_format: + _compiled_format = self.compile_format(log_format) + AccessLogger._FORMAT_CACHE[log_format] = _compiled_format + self._log_format, self._methods = _compiled_format + + def compile_format(self, log_format): + """Translate log_format into form usable by modulo formatting + + All known atoms will be replaced with %s + Also methods for formatting of those atoms will be added to + _methods in apropriate order + + For example we have log_format = "%a %t" + This format will be translated to "%s %s" + Also contents of _methods will be + [self._format_a, self._format_t] + These method will be called and results will be passed + to translated string format. + + Each _format_* method receive 'args' which is list of arguments + given to self.log + + Exceptions are _format_e, _format_i and _format_o methods which + also receive key name (by functools.partial) + + """ + + log_format = log_format.replace("%l", "-") + log_format = log_format.replace("%u", "-") + methods = [] + + for atom in self.FORMAT_RE.findall(log_format): + if atom[1] == '': + methods.append(getattr(AccessLogger, '_format_%s' % atom[0])) + else: + m = getattr(AccessLogger, '_format_%s' % atom[2]) + methods.append(functools.partial(m, atom[1])) + log_format = self.FORMAT_RE.sub(r'%s', log_format) + log_format = self.CLEANUP_RE.sub(r'%\1', log_format) + return log_format, methods + + @staticmethod + def _format_e(key, args): + return (args[1] or {}).get(key, '-') + + @staticmethod + def _format_i(key, args): + if not args[0]: + return '(no headers)' + # suboptimal, make istr(key) once + return args[0].headers.get(key, '-') + + @staticmethod + def _format_o(key, args): + # suboptimal, make istr(key) once + return args[2].headers.get(key, '-') + + @staticmethod + def _format_a(args): + if args[3] is None: + return '-' + peername = args[3].get_extra_info('peername') + if isinstance(peername, (list, tuple)): + return peername[0] + else: + return peername + + @staticmethod + def _format_t(args): + return datetime.datetime.utcnow().strftime('[%d/%b/%Y:%H:%M:%S +0000]') + + @staticmethod + def _format_P(args): + return "<%s>" % os.getpid() + + @staticmethod + def _format_r(args): + msg = args[0] + if not msg: + return '-' + return '%s %s HTTP/%s.%s' % tuple((msg.method, + msg.path) + msg.version) + + @staticmethod + def _format_s(args): + return args[2].status + + @staticmethod + def _format_b(args): + return args[2].body_length + + @staticmethod + def _format_O(args): + return args[2].output_length + + @staticmethod + def _format_T(args): + return round(args[4]) + + @staticmethod + def _format_Tf(args): + return '%06f' % args[4] + + @staticmethod + def _format_D(args): + return round(args[4] * 1000000) + + def _format_line(self, args): + return tuple(m(args) for m in self._methods) + + def log(self, message, environ, response, transport, time): + """Log access. + + :param message: Request object. May be None. + :param environ: Environment dict. May be None. + :param response: Response object. + :param transport: Tansport object. May be None + :param float time: Time taken to serve the request. + """ + try: + self.logger.info(self._log_format % self._format_line( + [message, environ, response, transport, time])) + except Exception: + self.logger.exception("Error in logging") class reify: @@ -380,336 +418,117 @@ class reify: """ - def __init__(self, wrapped: Callable[..., Any]) -> None: + def __init__(self, wrapped): self.wrapped = wrapped - self.__doc__ = wrapped.__doc__ + try: + self.__doc__ = wrapped.__doc__ + except: # pragma: no cover + self.__doc__ = "" self.name = wrapped.__name__ - def __get__(self, inst: Any, owner: Any) -> Any: - try: - try: - return inst._cache[self.name] - except KeyError: - val = self.wrapped(inst) - inst._cache[self.name] = val - return val - except AttributeError: - if inst is None: - return self - raise - - def __set__(self, inst: Any, value: Any) -> None: + def __get__(self, inst, owner, _sentinel=sentinel): + if inst is None: + return self + val = inst.__dict__.get(self.name, _sentinel) + if val is not _sentinel: + return val + val = self.wrapped(inst) + inst.__dict__[self.name] = val + return val + + def __set__(self, inst, value): raise AttributeError("reified property is read-only") -reify_py = reify +# The unreserved URI characters (RFC 3986) +UNRESERVED_SET = frozenset( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + + "0123456789-._~") -try: - from ._helpers import reify as reify_c - if not NO_EXTENSIONS: - reify = reify_c # type: ignore -except ImportError: - pass -_ipv4_pattern = (r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}' - r'(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$') +def unquote_unreserved(uri): + """Un-escape any percent-escape sequences in a URI that are unreserved + characters. This leaves all reserved, illegal and non-ASCII bytes encoded. + """ + parts = uri.split('%') + for i in range(1, len(parts)): + h = parts[i][0:2] + if len(h) == 2 and h.isalnum(): + try: + c = chr(int(h, 16)) + except ValueError: + raise InvalidURL("Invalid percent-escape sequence: '%s'" % h) + + if c in UNRESERVED_SET: + parts[i] = c + parts[i][2:] + else: + parts[i] = '%' + parts[i] + else: + parts[i] = '%' + parts[i] + return ''.join(parts) + + +def requote_uri(uri): + """Re-quote the given URI. + + This function passes the given URI through an unquote/quote cycle to + ensure that it is fully and consistently quoted. + """ + safe_with_percent = "!#$%&'()*+,/:;=?@[]~" + safe_without_percent = "!#$&'()*+,/:;=?@[]~" + try: + # Unquote only the unreserved characters + # Then quote only illegal characters (do not quote reserved, + # unreserved, or '%') + return quote(unquote_unreserved(uri), safe=safe_with_percent) + except InvalidURL: + # We couldn't unquote the given URI, so let's try quoting it, but + # there may be unquoted '%'s in the URI. We need to make sure they're + # properly quoted so they do not cause issues elsewhere. + return quote(uri, safe=safe_without_percent) + + +_ipv4_pattern = ('^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}' + '(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$') _ipv6_pattern = ( - r'^(?:(?:(?:[A-F0-9]{1,4}:){6}|(?=(?:[A-F0-9]{0,4}:){0,6}' - r'(?:[0-9]{1,3}\.){3}[0-9]{1,3}$)(([0-9A-F]{1,4}:){0,5}|:)' - r'((:[0-9A-F]{1,4}){1,5}:|:)|::(?:[A-F0-9]{1,4}:){5})' - r'(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}' - r'(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])|(?:[A-F0-9]{1,4}:){7}' - r'[A-F0-9]{1,4}|(?=(?:[A-F0-9]{0,4}:){0,7}[A-F0-9]{0,4}$)' - r'(([0-9A-F]{1,4}:){1,7}|:)((:[0-9A-F]{1,4}){1,7}|:)|(?:[A-F0-9]{1,4}:){7}' - r':|:(:[A-F0-9]{1,4}){7})$') + '^(?:(?:(?:[A-F0-9]{1,4}:){6}|(?=(?:[A-F0-9]{0,4}:){0,6}' + '(?:[0-9]{1,3}\.){3}[0-9]{1,3}$)(([0-9A-F]{1,4}:){0,5}|:)' + '((:[0-9A-F]{1,4}){1,5}:|:)|::(?:[A-F0-9]{1,4}:){5})' + '(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}' + '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])|(?:[A-F0-9]{1,4}:){7}' + '[A-F0-9]{1,4}|(?=(?:[A-F0-9]{0,4}:){0,7}[A-F0-9]{0,4}$)' + '(([0-9A-F]{1,4}:){1,7}|:)((:[0-9A-F]{1,4}){1,7}|:)|(?:[A-F0-9]{1,4}:){7}' + ':|:(:[A-F0-9]{1,4}){7})$') _ipv4_regex = re.compile(_ipv4_pattern) _ipv6_regex = re.compile(_ipv6_pattern, flags=re.IGNORECASE) _ipv4_regexb = re.compile(_ipv4_pattern.encode('ascii')) _ipv6_regexb = re.compile(_ipv6_pattern.encode('ascii'), flags=re.IGNORECASE) -def _is_ip_address( - regex: Pattern[str], regexb: Pattern[bytes], - host: Optional[Union[str, bytes]]) -> bool: +def is_ip_address(host): if host is None: return False if isinstance(host, str): - return bool(regex.match(host)) + if _ipv4_regex.match(host) or _ipv6_regex.match(host): + return True + else: + return False elif isinstance(host, (bytes, bytearray, memoryview)): - return bool(regexb.match(host)) + if _ipv4_regexb.match(host) or _ipv6_regexb.match(host): + return True + else: + return False else: raise TypeError("{} [{}] is not a str or bytes" .format(host, type(host))) -is_ipv4_address = functools.partial(_is_ip_address, _ipv4_regex, _ipv4_regexb) -is_ipv6_address = functools.partial(_is_ip_address, _ipv6_regex, _ipv6_regexb) - - -def is_ip_address( - host: Optional[Union[str, bytes, bytearray, memoryview]]) -> bool: - return is_ipv4_address(host) or is_ipv6_address(host) - - -def next_whole_second() -> datetime.datetime: - """Return current time rounded up to the next whole second.""" - return ( - datetime.datetime.now( - datetime.timezone.utc).replace(microsecond=0) + - datetime.timedelta(seconds=0) - ) - - -_cached_current_datetime = None # type: Optional[int] -_cached_formatted_datetime = "" - - -def rfc822_formatted_time() -> str: - global _cached_current_datetime - global _cached_formatted_datetime - - now = int(time.time()) - if now != _cached_current_datetime: - # Weekday and month names for HTTP date/time formatting; - # always English! - # Tuples are constants stored in codeobject! - _weekdayname = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun") - _monthname = ("", # Dummy so we can use 1-based month numbers - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec") - - year, month, day, hh, mm, ss, wd, *tail = time.gmtime(now) - _cached_formatted_datetime = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % ( - _weekdayname[wd], day, _monthname[month], year, hh, mm, ss - ) - _cached_current_datetime = now - return _cached_formatted_datetime - - -def _weakref_handle(info): # type: ignore - ref, name = info - ob = ref() - if ob is not None: - with suppress(Exception): - getattr(ob, name)() - - -def weakref_handle(ob, name, timeout, loop, ceil_timeout=True): # type: ignore - if timeout is not None and timeout > 0: - when = loop.time() + timeout - if ceil_timeout: - when = ceil(when) - - return loop.call_at(when, _weakref_handle, (weakref.ref(ob), name)) - - -def call_later(cb, timeout, loop): # type: ignore - if timeout is not None and timeout > 0: - when = ceil(loop.time() + timeout) - return loop.call_at(when, cb) - - -class TimeoutHandle: - """ Timeout handle """ - - def __init__(self, - loop: asyncio.AbstractEventLoop, - timeout: Optional[float]) -> None: - self._timeout = timeout - self._loop = loop - self._callbacks = [] # type: List[Tuple[Callable[..., None], Tuple[Any, ...], Dict[str, Any]]] # noqa - - def register(self, callback: Callable[..., None], - *args: Any, **kwargs: Any) -> None: - self._callbacks.append((callback, args, kwargs)) - - def close(self) -> None: - self._callbacks.clear() - - def start(self) -> Optional[asyncio.Handle]: - if self._timeout is not None and self._timeout > 0: - at = ceil(self._loop.time() + self._timeout) - return self._loop.call_at(at, self.__call__) - else: - return None - - def timer(self) -> 'BaseTimerContext': - if self._timeout is not None and self._timeout > 0: - timer = TimerContext(self._loop) - self.register(timer.timeout) - return timer - else: - return TimerNoop() - - def __call__(self) -> None: - for cb, args, kwargs in self._callbacks: - with suppress(Exception): - cb(*args, **kwargs) - - self._callbacks.clear() - - -class BaseTimerContext(ContextManager['BaseTimerContext']): - pass - - -class TimerNoop(BaseTimerContext): - - def __enter__(self) -> BaseTimerContext: - return self - - def __exit__(self, exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType]) -> Optional[bool]: - return False - - -class TimerContext(BaseTimerContext): - """ Low resolution timeout context manager """ - - def __init__(self, loop: asyncio.AbstractEventLoop) -> None: - self._loop = loop - self._tasks = [] # type: List[asyncio.Task[Any]] - self._cancelled = False - - def __enter__(self) -> BaseTimerContext: - task = current_task(loop=self._loop) - - if task is None: - raise RuntimeError('Timeout context manager should be used ' - 'inside a task') - - if self._cancelled: - task.cancel() - raise asyncio.TimeoutError from None - - self._tasks.append(task) - return self - - def __exit__(self, exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType]) -> Optional[bool]: - if self._tasks: - self._tasks.pop() - - if exc_type is asyncio.CancelledError and self._cancelled: - raise asyncio.TimeoutError from None - return None - - def timeout(self) -> None: - if not self._cancelled: - for task in set(self._tasks): - task.cancel() - - self._cancelled = True - - -class CeilTimeout(async_timeout.timeout): - - def __enter__(self) -> async_timeout.timeout: - if self._timeout is not None: - self._task = current_task(loop=self._loop) - if self._task is None: - raise RuntimeError( - 'Timeout context manager should be used inside a task') - self._cancel_handler = self._loop.call_at( - ceil(self._loop.time() + self._timeout), self._cancel_task) - return self - - -class HeadersMixin: - - ATTRS = frozenset([ - '_content_type', '_content_dict', '_stored_content_type']) - - _content_type = None # type: Optional[str] - _content_dict = None # type: Optional[Dict[str, str]] - _stored_content_type = sentinel - - def _parse_content_type(self, raw: str) -> None: - self._stored_content_type = raw - if raw is None: - # default value according to RFC 2616 - self._content_type = 'application/octet-stream' - self._content_dict = {} - else: - self._content_type, self._content_dict = cgi.parse_header(raw) - - @property - def content_type(self) -> str: - """The value of content part for Content-Type HTTP header.""" - raw = self._headers.get(hdrs.CONTENT_TYPE) # type: ignore - if self._stored_content_type != raw: - self._parse_content_type(raw) - return self._content_type # type: ignore - - @property - def charset(self) -> Optional[str]: - """The value of charset part for Content-Type HTTP header.""" - raw = self._headers.get(hdrs.CONTENT_TYPE) # type: ignore - if self._stored_content_type != raw: - self._parse_content_type(raw) - return self._content_dict.get('charset') # type: ignore - - @property - def content_length(self) -> Optional[int]: - """The value of Content-Length HTTP header.""" - content_length = self._headers.get(hdrs.CONTENT_LENGTH) # type: ignore - - if content_length is not None: - return int(content_length) - else: - return None - - -def set_result(fut: 'asyncio.Future[_T]', result: _T) -> None: - if not fut.done(): - fut.set_result(result) - - -def set_exception(fut: 'asyncio.Future[_T]', exc: BaseException) -> None: - if not fut.done(): - fut.set_exception(exc) - - -class ChainMapProxy(Mapping[str, Any]): - __slots__ = ('_maps',) - - def __init__(self, maps: Iterable[Mapping[str, Any]]) -> None: - self._maps = tuple(maps) - - def __init_subclass__(cls) -> None: - raise TypeError("Inheritance class {} from ChainMapProxy " - "is forbidden".format(cls.__name__)) - - def __getitem__(self, key: str) -> Any: - for mapping in self._maps: - try: - return mapping[key] - except KeyError: - pass - raise KeyError(key) - - def get(self, key: str, default: Any=None) -> Any: - return self[key] if key in self else default - - def __len__(self) -> int: - # reuses stored hash values if possible - return len(set().union(*self._maps)) # type: ignore - - def __iter__(self) -> Iterator[str]: - d = {} # type: Dict[str, Any] - for mapping in reversed(self._maps): - # reuses stored hash values if possible - d.update(mapping) - return iter(d) - - def __contains__(self, key: object) -> bool: - return any(key in m for m in self._maps) - - def __bool__(self) -> bool: - return any(self._maps) - - def __repr__(self) -> str: - content = ", ".join(map(repr, self._maps)) - return 'ChainMapProxy({})'.format(content) +def _get_kwarg(kwargs, old, new, value): + val = kwargs.pop(old, sentinel) + if val is not sentinel: + warnings.warn("{} is deprecated, use {} instead".format(old, new), + DeprecationWarning, + stacklevel=3) + return val + else: + return value diff --git a/venv/Lib/site-packages/aiohttp/http.py b/venv/Lib/site-packages/aiohttp/http.py deleted file mode 100644 index 5f8109c2..00000000 --- a/venv/Lib/site-packages/aiohttp/http.py +++ /dev/null @@ -1,50 +0,0 @@ -import http.server -import sys -from typing import Mapping, Tuple # noqa - -from . import __version__ -from .http_exceptions import HttpProcessingError as HttpProcessingError -from .http_parser import HeadersParser as HeadersParser -from .http_parser import HttpParser as HttpParser -from .http_parser import HttpRequestParser as HttpRequestParser -from .http_parser import HttpResponseParser as HttpResponseParser -from .http_parser import RawRequestMessage as RawRequestMessage -from .http_parser import RawResponseMessage as RawResponseMessage -from .http_websocket import WS_CLOSED_MESSAGE as WS_CLOSED_MESSAGE -from .http_websocket import WS_CLOSING_MESSAGE as WS_CLOSING_MESSAGE -from .http_websocket import WS_KEY as WS_KEY -from .http_websocket import WebSocketError as WebSocketError -from .http_websocket import WebSocketReader as WebSocketReader -from .http_websocket import WebSocketWriter as WebSocketWriter -from .http_websocket import WSCloseCode as WSCloseCode -from .http_websocket import WSMessage as WSMessage -from .http_websocket import WSMsgType as WSMsgType -from .http_websocket import ws_ext_gen as ws_ext_gen -from .http_websocket import ws_ext_parse as ws_ext_parse -from .http_writer import HttpVersion as HttpVersion -from .http_writer import HttpVersion10 as HttpVersion10 -from .http_writer import HttpVersion11 as HttpVersion11 -from .http_writer import StreamWriter as StreamWriter - -__all__ = ( - 'HttpProcessingError', 'RESPONSES', 'SERVER_SOFTWARE', - - # .http_writer - 'StreamWriter', 'HttpVersion', 'HttpVersion10', 'HttpVersion11', - - # .http_parser - 'HeadersParser', 'HttpParser', - 'HttpRequestParser', 'HttpResponseParser', - 'RawRequestMessage', 'RawResponseMessage', - - # .http_websocket - 'WS_CLOSED_MESSAGE', 'WS_CLOSING_MESSAGE', 'WS_KEY', - 'WebSocketReader', 'WebSocketWriter', 'ws_ext_gen', 'ws_ext_parse', - 'WSMessage', 'WebSocketError', 'WSMsgType', 'WSCloseCode', -) - - -SERVER_SOFTWARE = 'Python/{0[0]}.{0[1]} aiohttp/{1}'.format( - sys.version_info, __version__) # type: str - -RESPONSES = http.server.BaseHTTPRequestHandler.responses # type: Mapping[int, Tuple[str, str]] # noqa diff --git a/venv/Lib/site-packages/aiohttp/http_exceptions.py b/venv/Lib/site-packages/aiohttp/http_exceptions.py deleted file mode 100644 index 3c8b0d83..00000000 --- a/venv/Lib/site-packages/aiohttp/http_exceptions.py +++ /dev/null @@ -1,108 +0,0 @@ -"""Low-level http related exceptions.""" - - -from typing import Optional, Union - -from .typedefs import _CIMultiDict - -__all__ = ('HttpProcessingError',) - - -class HttpProcessingError(Exception): - """HTTP error. - - Shortcut for raising HTTP errors with custom code, message and headers. - - code: HTTP Error code. - message: (optional) Error message. - headers: (optional) Headers to be sent in response, a list of pairs - """ - - code = 0 - message = '' - headers = None - - def __init__(self, *, - code: Optional[int]=None, - message: str='', - headers: Optional[_CIMultiDict]=None) -> None: - if code is not None: - self.code = code - self.headers = headers - self.message = message - - def __str__(self) -> str: - return "%s, message=%r" % (self.code, self.message) - - def __repr__(self) -> str: - return "<%s: %s>" % (self.__class__.__name__, self) - - -class BadHttpMessage(HttpProcessingError): - - code = 400 - message = 'Bad Request' - - def __init__(self, message: str, *, - headers: Optional[_CIMultiDict]=None) -> None: - super().__init__(message=message, headers=headers) - self.args = (message,) - - -class HttpBadRequest(BadHttpMessage): - - code = 400 - message = 'Bad Request' - - -class PayloadEncodingError(BadHttpMessage): - """Base class for payload errors""" - - -class ContentEncodingError(PayloadEncodingError): - """Content encoding error.""" - - -class TransferEncodingError(PayloadEncodingError): - """transfer encoding error.""" - - -class ContentLengthError(PayloadEncodingError): - """Not enough data for satisfy content length header.""" - - -class LineTooLong(BadHttpMessage): - - def __init__(self, line: str, - limit: str='Unknown', - actual_size: str='Unknown') -> None: - super().__init__( - "Got more than %s bytes (%s) when reading %s." % ( - limit, actual_size, line)) - self.args = (line, limit, actual_size) - - -class InvalidHeader(BadHttpMessage): - - def __init__(self, hdr: Union[bytes, str]) -> None: - if isinstance(hdr, bytes): - hdr = hdr.decode('utf-8', 'surrogateescape') - super().__init__('Invalid HTTP Header: {}'.format(hdr)) - self.hdr = hdr - self.args = (hdr,) - - -class BadStatusLine(BadHttpMessage): - - def __init__(self, line: str='') -> None: - if not isinstance(line, str): - line = repr(line) - self.args = (line,) - self.line = line - - __str__ = Exception.__str__ - __repr__ = Exception.__repr__ - - -class InvalidURLError(BadHttpMessage): - pass diff --git a/venv/Lib/site-packages/aiohttp/http_parser.py b/venv/Lib/site-packages/aiohttp/http_parser.py deleted file mode 100644 index 9e22d102..00000000 --- a/venv/Lib/site-packages/aiohttp/http_parser.py +++ /dev/null @@ -1,764 +0,0 @@ -import abc -import asyncio -import collections -import re -import string -import zlib -from enum import IntEnum -from typing import Any, List, Optional, Tuple, Type, Union # noqa - -from multidict import CIMultiDict, CIMultiDictProxy, istr -from yarl import URL - -from . import hdrs -from .base_protocol import BaseProtocol -from .helpers import NO_EXTENSIONS, BaseTimerContext -from .http_exceptions import ( - BadStatusLine, - ContentEncodingError, - ContentLengthError, - InvalidHeader, - LineTooLong, - TransferEncodingError, -) -from .http_writer import HttpVersion, HttpVersion10 -from .log import internal_logger -from .streams import EMPTY_PAYLOAD, StreamReader -from .typedefs import RawHeaders - -try: - import brotli - HAS_BROTLI = True -except ImportError: # pragma: no cover - HAS_BROTLI = False - - -__all__ = ( - 'HeadersParser', 'HttpParser', 'HttpRequestParser', 'HttpResponseParser', - 'RawRequestMessage', 'RawResponseMessage') - -ASCIISET = set(string.printable) - -# See https://tools.ietf.org/html/rfc7230#section-3.1.1 -# and https://tools.ietf.org/html/rfc7230#appendix-B -# -# method = token -# tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / -# "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA -# token = 1*tchar -METHRE = re.compile(r"[!#$%&'*+\-.^_`|~0-9A-Za-z]+") -VERSRE = re.compile(r'HTTP/(\d+).(\d+)') -HDRRE = re.compile(rb'[\x00-\x1F\x7F()<>@,;:\[\]={} \t\\\\\"]') - -RawRequestMessage = collections.namedtuple( - 'RawRequestMessage', - ['method', 'path', 'version', 'headers', 'raw_headers', - 'should_close', 'compression', 'upgrade', 'chunked', 'url']) - -RawResponseMessage = collections.namedtuple( - 'RawResponseMessage', - ['version', 'code', 'reason', 'headers', 'raw_headers', - 'should_close', 'compression', 'upgrade', 'chunked']) - - -class ParseState(IntEnum): - - PARSE_NONE = 0 - PARSE_LENGTH = 1 - PARSE_CHUNKED = 2 - PARSE_UNTIL_EOF = 3 - - -class ChunkState(IntEnum): - PARSE_CHUNKED_SIZE = 0 - PARSE_CHUNKED_CHUNK = 1 - PARSE_CHUNKED_CHUNK_EOF = 2 - PARSE_MAYBE_TRAILERS = 3 - PARSE_TRAILERS = 4 - - -class HeadersParser: - def __init__(self, - max_line_size: int=8190, - max_headers: int=32768, - max_field_size: int=8190) -> None: - self.max_line_size = max_line_size - self.max_headers = max_headers - self.max_field_size = max_field_size - - def parse_headers( - self, - lines: List[bytes] - ) -> Tuple['CIMultiDictProxy[str]', RawHeaders]: - headers = CIMultiDict() # type: CIMultiDict[str] - raw_headers = [] - - lines_idx = 1 - line = lines[1] - line_count = len(lines) - - while line: - # Parse initial header name : value pair. - try: - bname, bvalue = line.split(b':', 1) - except ValueError: - raise InvalidHeader(line) from None - - bname = bname.strip(b' \t') - bvalue = bvalue.lstrip() - if HDRRE.search(bname): - raise InvalidHeader(bname) - if len(bname) > self.max_field_size: - raise LineTooLong( - "request header name {}".format( - bname.decode("utf8", "xmlcharrefreplace")), - str(self.max_field_size), - str(len(bname))) - - header_length = len(bvalue) - - # next line - lines_idx += 1 - line = lines[lines_idx] - - # consume continuation lines - continuation = line and line[0] in (32, 9) # (' ', '\t') - - if continuation: - bvalue_lst = [bvalue] - while continuation: - header_length += len(line) - if header_length > self.max_field_size: - raise LineTooLong( - 'request header field {}'.format( - bname.decode("utf8", "xmlcharrefreplace")), - str(self.max_field_size), - str(header_length)) - bvalue_lst.append(line) - - # next line - lines_idx += 1 - if lines_idx < line_count: - line = lines[lines_idx] - if line: - continuation = line[0] in (32, 9) # (' ', '\t') - else: - line = b'' - break - bvalue = b''.join(bvalue_lst) - else: - if header_length > self.max_field_size: - raise LineTooLong( - 'request header field {}'.format( - bname.decode("utf8", "xmlcharrefreplace")), - str(self.max_field_size), - str(header_length)) - - bvalue = bvalue.strip() - name = bname.decode('utf-8', 'surrogateescape') - value = bvalue.decode('utf-8', 'surrogateescape') - - headers.add(name, value) - raw_headers.append((bname, bvalue)) - - return (CIMultiDictProxy(headers), tuple(raw_headers)) - - -class HttpParser(abc.ABC): - - def __init__(self, protocol: Optional[BaseProtocol]=None, - loop: Optional[asyncio.AbstractEventLoop]=None, - max_line_size: int=8190, - max_headers: int=32768, - max_field_size: int=8190, - timer: Optional[BaseTimerContext]=None, - code: Optional[int]=None, - method: Optional[str]=None, - readall: bool=False, - payload_exception: Optional[Type[BaseException]]=None, - response_with_body: bool=True, - read_until_eof: bool=False, - auto_decompress: bool=True) -> None: - self.protocol = protocol - self.loop = loop - self.max_line_size = max_line_size - self.max_headers = max_headers - self.max_field_size = max_field_size - self.timer = timer - self.code = code - self.method = method - self.readall = readall - self.payload_exception = payload_exception - self.response_with_body = response_with_body - self.read_until_eof = read_until_eof - - self._lines = [] # type: List[bytes] - self._tail = b'' - self._upgraded = False - self._payload = None - self._payload_parser = None # type: Optional[HttpPayloadParser] - self._auto_decompress = auto_decompress - self._headers_parser = HeadersParser(max_line_size, - max_headers, - max_field_size) - - @abc.abstractmethod - def parse_message(self, lines: List[bytes]) -> Any: - pass - - def feed_eof(self) -> Any: - if self._payload_parser is not None: - self._payload_parser.feed_eof() - self._payload_parser = None - else: - # try to extract partial message - if self._tail: - self._lines.append(self._tail) - - if self._lines: - if self._lines[-1] != '\r\n': - self._lines.append(b'') - try: - return self.parse_message(self._lines) - except Exception: - return None - - def feed_data( - self, - data: bytes, - SEP: bytes=b'\r\n', - EMPTY: bytes=b'', - CONTENT_LENGTH: istr=hdrs.CONTENT_LENGTH, - METH_CONNECT: str=hdrs.METH_CONNECT, - SEC_WEBSOCKET_KEY1: istr=hdrs.SEC_WEBSOCKET_KEY1 - ) -> Tuple[List[Any], bool, bytes]: - - messages = [] - - if self._tail: - data, self._tail = self._tail + data, b'' - - data_len = len(data) - start_pos = 0 - loop = self.loop - - while start_pos < data_len: - - # read HTTP message (request/response line + headers), \r\n\r\n - # and split by lines - if self._payload_parser is None and not self._upgraded: - pos = data.find(SEP, start_pos) - # consume \r\n - if pos == start_pos and not self._lines: - start_pos = pos + 2 - continue - - if pos >= start_pos: - # line found - self._lines.append(data[start_pos:pos]) - start_pos = pos + 2 - - # \r\n\r\n found - if self._lines[-1] == EMPTY: - try: - msg = self.parse_message(self._lines) - finally: - self._lines.clear() - - # payload length - length = msg.headers.get(CONTENT_LENGTH) - if length is not None: - try: - length = int(length) - except ValueError: - raise InvalidHeader(CONTENT_LENGTH) - if length < 0: - raise InvalidHeader(CONTENT_LENGTH) - - # do not support old websocket spec - if SEC_WEBSOCKET_KEY1 in msg.headers: - raise InvalidHeader(SEC_WEBSOCKET_KEY1) - - self._upgraded = msg.upgrade - - method = getattr(msg, 'method', self.method) - - assert self.protocol is not None - # calculate payload - if ((length is not None and length > 0) or - msg.chunked and not msg.upgrade): - payload = StreamReader( - self.protocol, timer=self.timer, loop=loop) - payload_parser = HttpPayloadParser( - payload, length=length, - chunked=msg.chunked, method=method, - compression=msg.compression, - code=self.code, readall=self.readall, - response_with_body=self.response_with_body, - auto_decompress=self._auto_decompress) - if not payload_parser.done: - self._payload_parser = payload_parser - elif method == METH_CONNECT: - payload = StreamReader( - self.protocol, timer=self.timer, loop=loop) - self._upgraded = True - self._payload_parser = HttpPayloadParser( - payload, method=msg.method, - compression=msg.compression, readall=True, - auto_decompress=self._auto_decompress) - else: - if (getattr(msg, 'code', 100) >= 199 and - length is None and self.read_until_eof): - payload = StreamReader( - self.protocol, timer=self.timer, loop=loop) - payload_parser = HttpPayloadParser( - payload, length=length, - chunked=msg.chunked, method=method, - compression=msg.compression, - code=self.code, readall=True, - response_with_body=self.response_with_body, - auto_decompress=self._auto_decompress) - if not payload_parser.done: - self._payload_parser = payload_parser - else: - payload = EMPTY_PAYLOAD # type: ignore - - messages.append((msg, payload)) - else: - self._tail = data[start_pos:] - data = EMPTY - break - - # no parser, just store - elif self._payload_parser is None and self._upgraded: - assert not self._lines - break - - # feed payload - elif data and start_pos < data_len: - assert not self._lines - assert self._payload_parser is not None - try: - eof, data = self._payload_parser.feed_data( - data[start_pos:]) - except BaseException as exc: - if self.payload_exception is not None: - self._payload_parser.payload.set_exception( - self.payload_exception(str(exc))) - else: - self._payload_parser.payload.set_exception(exc) - - eof = True - data = b'' - - if eof: - start_pos = 0 - data_len = len(data) - self._payload_parser = None - continue - else: - break - - if data and start_pos < data_len: - data = data[start_pos:] - else: - data = EMPTY - - return messages, self._upgraded, data - - def parse_headers( - self, - lines: List[bytes] - ) -> Tuple['CIMultiDictProxy[str]', - RawHeaders, - Optional[bool], - Optional[str], - bool, - bool]: - """Parses RFC 5322 headers from a stream. - - Line continuations are supported. Returns list of header name - and value pairs. Header name is in upper case. - """ - headers, raw_headers = self._headers_parser.parse_headers(lines) - close_conn = None - encoding = None - upgrade = False - chunked = False - - # keep-alive - conn = headers.get(hdrs.CONNECTION) - if conn: - v = conn.lower() - if v == 'close': - close_conn = True - elif v == 'keep-alive': - close_conn = False - elif v == 'upgrade': - upgrade = True - - # encoding - enc = headers.get(hdrs.CONTENT_ENCODING) - if enc: - enc = enc.lower() - if enc in ('gzip', 'deflate', 'br'): - encoding = enc - - # chunking - te = headers.get(hdrs.TRANSFER_ENCODING) - if te and 'chunked' in te.lower(): - chunked = True - - return (headers, raw_headers, close_conn, encoding, upgrade, chunked) - - -class HttpRequestParser(HttpParser): - """Read request status line. Exception .http_exceptions.BadStatusLine - could be raised in case of any errors in status line. - Returns RawRequestMessage. - """ - - def parse_message(self, lines: List[bytes]) -> Any: - # request line - line = lines[0].decode('utf-8', 'surrogateescape') - try: - method, path, version = line.split(None, 2) - except ValueError: - raise BadStatusLine(line) from None - - if len(path) > self.max_line_size: - raise LineTooLong( - 'Status line is too long', - str(self.max_line_size), - str(len(path))) - - # method - if not METHRE.match(method): - raise BadStatusLine(method) - - # version - try: - if version.startswith('HTTP/'): - n1, n2 = version[5:].split('.', 1) - version_o = HttpVersion(int(n1), int(n2)) - else: - raise BadStatusLine(version) - except Exception: - raise BadStatusLine(version) - - # read headers - (headers, raw_headers, - close, compression, upgrade, chunked) = self.parse_headers(lines) - - if close is None: # then the headers weren't set in the request - if version_o <= HttpVersion10: # HTTP 1.0 must asks to not close - close = True - else: # HTTP 1.1 must ask to close. - close = False - - return RawRequestMessage( - method, path, version_o, headers, raw_headers, - close, compression, upgrade, chunked, URL(path)) - - -class HttpResponseParser(HttpParser): - """Read response status line and headers. - - BadStatusLine could be raised in case of any errors in status line. - Returns RawResponseMessage""" - - def parse_message(self, lines: List[bytes]) -> Any: - line = lines[0].decode('utf-8', 'surrogateescape') - try: - version, status = line.split(None, 1) - except ValueError: - raise BadStatusLine(line) from None - - try: - status, reason = status.split(None, 1) - except ValueError: - reason = '' - - if len(reason) > self.max_line_size: - raise LineTooLong( - 'Status line is too long', - str(self.max_line_size), - str(len(reason))) - - # version - match = VERSRE.match(version) - if match is None: - raise BadStatusLine(line) - version_o = HttpVersion(int(match.group(1)), int(match.group(2))) - - # The status code is a three-digit number - try: - status_i = int(status) - except ValueError: - raise BadStatusLine(line) from None - - if status_i > 999: - raise BadStatusLine(line) - - # read headers - (headers, raw_headers, - close, compression, upgrade, chunked) = self.parse_headers(lines) - - if close is None: - close = version_o <= HttpVersion10 - - return RawResponseMessage( - version_o, status_i, reason.strip(), - headers, raw_headers, close, compression, upgrade, chunked) - - -class HttpPayloadParser: - - def __init__(self, payload: StreamReader, - length: Optional[int]=None, - chunked: bool=False, - compression: Optional[str]=None, - code: Optional[int]=None, - method: Optional[str]=None, - readall: bool=False, - response_with_body: bool=True, - auto_decompress: bool=True) -> None: - self._length = 0 - self._type = ParseState.PARSE_NONE - self._chunk = ChunkState.PARSE_CHUNKED_SIZE - self._chunk_size = 0 - self._chunk_tail = b'' - self._auto_decompress = auto_decompress - self.done = False - - # payload decompression wrapper - if response_with_body and compression and self._auto_decompress: - real_payload = DeflateBuffer(payload, compression) # type: Union[StreamReader, DeflateBuffer] # noqa - else: - real_payload = payload - - # payload parser - if not response_with_body: - # don't parse payload if it's not expected to be received - self._type = ParseState.PARSE_NONE - real_payload.feed_eof() - self.done = True - - elif chunked: - self._type = ParseState.PARSE_CHUNKED - elif length is not None: - self._type = ParseState.PARSE_LENGTH - self._length = length - if self._length == 0: - real_payload.feed_eof() - self.done = True - else: - if readall and code != 204: - self._type = ParseState.PARSE_UNTIL_EOF - elif method in ('PUT', 'POST'): - internal_logger.warning( # pragma: no cover - 'Content-Length or Transfer-Encoding header is required') - self._type = ParseState.PARSE_NONE - real_payload.feed_eof() - self.done = True - - self.payload = real_payload - - def feed_eof(self) -> None: - if self._type == ParseState.PARSE_UNTIL_EOF: - self.payload.feed_eof() - elif self._type == ParseState.PARSE_LENGTH: - raise ContentLengthError( - "Not enough data for satisfy content length header.") - elif self._type == ParseState.PARSE_CHUNKED: - raise TransferEncodingError( - "Not enough data for satisfy transfer length header.") - - def feed_data(self, - chunk: bytes, - SEP: bytes=b'\r\n', - CHUNK_EXT: bytes=b';') -> Tuple[bool, bytes]: - # Read specified amount of bytes - if self._type == ParseState.PARSE_LENGTH: - required = self._length - chunk_len = len(chunk) - - if required >= chunk_len: - self._length = required - chunk_len - self.payload.feed_data(chunk, chunk_len) - if self._length == 0: - self.payload.feed_eof() - return True, b'' - else: - self._length = 0 - self.payload.feed_data(chunk[:required], required) - self.payload.feed_eof() - return True, chunk[required:] - - # Chunked transfer encoding parser - elif self._type == ParseState.PARSE_CHUNKED: - if self._chunk_tail: - chunk = self._chunk_tail + chunk - self._chunk_tail = b'' - - while chunk: - - # read next chunk size - if self._chunk == ChunkState.PARSE_CHUNKED_SIZE: - pos = chunk.find(SEP) - if pos >= 0: - i = chunk.find(CHUNK_EXT, 0, pos) - if i >= 0: - size_b = chunk[:i] # strip chunk-extensions - else: - size_b = chunk[:pos] - - try: - size = int(bytes(size_b), 16) - except ValueError: - exc = TransferEncodingError( - chunk[:pos].decode('ascii', 'surrogateescape')) - self.payload.set_exception(exc) - raise exc from None - - chunk = chunk[pos+2:] - if size == 0: # eof marker - self._chunk = ChunkState.PARSE_MAYBE_TRAILERS - else: - self._chunk = ChunkState.PARSE_CHUNKED_CHUNK - self._chunk_size = size - self.payload.begin_http_chunk_receiving() - else: - self._chunk_tail = chunk - return False, b'' - - # read chunk and feed buffer - if self._chunk == ChunkState.PARSE_CHUNKED_CHUNK: - required = self._chunk_size - chunk_len = len(chunk) - - if required > chunk_len: - self._chunk_size = required - chunk_len - self.payload.feed_data(chunk, chunk_len) - return False, b'' - else: - self._chunk_size = 0 - self.payload.feed_data(chunk[:required], required) - chunk = chunk[required:] - self._chunk = ChunkState.PARSE_CHUNKED_CHUNK_EOF - self.payload.end_http_chunk_receiving() - - # toss the CRLF at the end of the chunk - if self._chunk == ChunkState.PARSE_CHUNKED_CHUNK_EOF: - if chunk[:2] == SEP: - chunk = chunk[2:] - self._chunk = ChunkState.PARSE_CHUNKED_SIZE - else: - self._chunk_tail = chunk - return False, b'' - - # if stream does not contain trailer, after 0\r\n - # we should get another \r\n otherwise - # trailers needs to be skiped until \r\n\r\n - if self._chunk == ChunkState.PARSE_MAYBE_TRAILERS: - if chunk[:2] == SEP: - # end of stream - self.payload.feed_eof() - return True, chunk[2:] - else: - self._chunk = ChunkState.PARSE_TRAILERS - - # read and discard trailer up to the CRLF terminator - if self._chunk == ChunkState.PARSE_TRAILERS: - pos = chunk.find(SEP) - if pos >= 0: - chunk = chunk[pos+2:] - self._chunk = ChunkState.PARSE_MAYBE_TRAILERS - else: - self._chunk_tail = chunk - return False, b'' - - # Read all bytes until eof - elif self._type == ParseState.PARSE_UNTIL_EOF: - self.payload.feed_data(chunk, len(chunk)) - - return False, b'' - - -class DeflateBuffer: - """DeflateStream decompress stream and feed data into specified stream.""" - - def __init__(self, out: StreamReader, encoding: Optional[str]) -> None: - self.out = out - self.size = 0 - self.encoding = encoding - self._started_decoding = False - - if encoding == 'br': - if not HAS_BROTLI: # pragma: no cover - raise ContentEncodingError( - 'Can not decode content-encoding: brotli (br). ' - 'Please install `brotlipy`') - self.decompressor = brotli.Decompressor() - else: - zlib_mode = (16 + zlib.MAX_WBITS - if encoding == 'gzip' else -zlib.MAX_WBITS) - self.decompressor = zlib.decompressobj(wbits=zlib_mode) - - def set_exception(self, exc: BaseException) -> None: - self.out.set_exception(exc) - - def feed_data(self, chunk: bytes, size: int) -> None: - self.size += size - try: - chunk = self.decompressor.decompress(chunk) - except Exception: - if not self._started_decoding and self.encoding == 'deflate': - self.decompressor = zlib.decompressobj() - try: - chunk = self.decompressor.decompress(chunk) - except Exception: - raise ContentEncodingError( - 'Can not decode content-encoding: %s' % self.encoding) - else: - raise ContentEncodingError( - 'Can not decode content-encoding: %s' % self.encoding) - - if chunk: - self._started_decoding = True - self.out.feed_data(chunk, len(chunk)) - - def feed_eof(self) -> None: - chunk = self.decompressor.flush() - - if chunk or self.size > 0: - self.out.feed_data(chunk, len(chunk)) - if self.encoding == 'deflate' and not self.decompressor.eof: - raise ContentEncodingError('deflate') - - self.out.feed_eof() - - def begin_http_chunk_receiving(self) -> None: - self.out.begin_http_chunk_receiving() - - def end_http_chunk_receiving(self) -> None: - self.out.end_http_chunk_receiving() - - -HttpRequestParserPy = HttpRequestParser -HttpResponseParserPy = HttpResponseParser -RawRequestMessagePy = RawRequestMessage -RawResponseMessagePy = RawResponseMessage - -try: - if not NO_EXTENSIONS: - from ._http_parser import (HttpRequestParser, # type: ignore # noqa - HttpResponseParser, - RawRequestMessage, - RawResponseMessage) - HttpRequestParserC = HttpRequestParser - HttpResponseParserC = HttpResponseParser - RawRequestMessageC = RawRequestMessage - RawResponseMessageC = RawResponseMessage -except ImportError: # pragma: no cover - pass diff --git a/venv/Lib/site-packages/aiohttp/http_websocket.py b/venv/Lib/site-packages/aiohttp/http_websocket.py deleted file mode 100644 index e331d691..00000000 --- a/venv/Lib/site-packages/aiohttp/http_websocket.py +++ /dev/null @@ -1,659 +0,0 @@ -"""WebSocket protocol versions 13 and 8.""" - -import asyncio -import collections -import json -import random -import re -import sys -import zlib -from enum import IntEnum -from struct import Struct -from typing import Any, Callable, List, Optional, Tuple, Union - -from .base_protocol import BaseProtocol -from .helpers import NO_EXTENSIONS -from .log import ws_logger -from .streams import DataQueue - -__all__ = ('WS_CLOSED_MESSAGE', 'WS_CLOSING_MESSAGE', 'WS_KEY', - 'WebSocketReader', 'WebSocketWriter', 'WSMessage', - 'WebSocketError', 'WSMsgType', 'WSCloseCode') - - -class WSCloseCode(IntEnum): - OK = 1000 - GOING_AWAY = 1001 - PROTOCOL_ERROR = 1002 - UNSUPPORTED_DATA = 1003 - INVALID_TEXT = 1007 - POLICY_VIOLATION = 1008 - MESSAGE_TOO_BIG = 1009 - MANDATORY_EXTENSION = 1010 - INTERNAL_ERROR = 1011 - SERVICE_RESTART = 1012 - TRY_AGAIN_LATER = 1013 - - -ALLOWED_CLOSE_CODES = {int(i) for i in WSCloseCode} - - -class WSMsgType(IntEnum): - # websocket spec types - CONTINUATION = 0x0 - TEXT = 0x1 - BINARY = 0x2 - PING = 0x9 - PONG = 0xa - CLOSE = 0x8 - - # aiohttp specific types - CLOSING = 0x100 - CLOSED = 0x101 - ERROR = 0x102 - - text = TEXT - binary = BINARY - ping = PING - pong = PONG - close = CLOSE - closing = CLOSING - closed = CLOSED - error = ERROR - - -WS_KEY = b'258EAFA5-E914-47DA-95CA-C5AB0DC85B11' - - -UNPACK_LEN2 = Struct('!H').unpack_from -UNPACK_LEN3 = Struct('!Q').unpack_from -UNPACK_CLOSE_CODE = Struct('!H').unpack -PACK_LEN1 = Struct('!BB').pack -PACK_LEN2 = Struct('!BBH').pack -PACK_LEN3 = Struct('!BBQ').pack -PACK_CLOSE_CODE = Struct('!H').pack -MSG_SIZE = 2 ** 14 -DEFAULT_LIMIT = 2 ** 16 - - -_WSMessageBase = collections.namedtuple('_WSMessageBase', - ['type', 'data', 'extra']) - - -class WSMessage(_WSMessageBase): - - def json(self, *, - loads: Callable[[Any], Any]=json.loads) -> Any: - """Return parsed JSON data. - - .. versionadded:: 0.22 - """ - return loads(self.data) - - -WS_CLOSED_MESSAGE = WSMessage(WSMsgType.CLOSED, None, None) -WS_CLOSING_MESSAGE = WSMessage(WSMsgType.CLOSING, None, None) - - -class WebSocketError(Exception): - """WebSocket protocol parser error.""" - - def __init__(self, code: int, message: str) -> None: - self.code = code - super().__init__(code, message) - - def __str__(self) -> str: - return self.args[1] - - -class WSHandshakeError(Exception): - """WebSocket protocol handshake error.""" - - -native_byteorder = sys.byteorder - - -# Used by _websocket_mask_python -_XOR_TABLE = [bytes(a ^ b for a in range(256)) for b in range(256)] - - -def _websocket_mask_python(mask: bytes, data: bytearray) -> None: - """Websocket masking function. - - `mask` is a `bytes` object of length 4; `data` is a `bytearray` - object of any length. The contents of `data` are masked with `mask`, - as specified in section 5.3 of RFC 6455. - - Note that this function mutates the `data` argument. - - This pure-python implementation may be replaced by an optimized - version when available. - - """ - assert isinstance(data, bytearray), data - assert len(mask) == 4, mask - - if data: - a, b, c, d = (_XOR_TABLE[n] for n in mask) - data[::4] = data[::4].translate(a) - data[1::4] = data[1::4].translate(b) - data[2::4] = data[2::4].translate(c) - data[3::4] = data[3::4].translate(d) - - -if NO_EXTENSIONS: # pragma: no cover - _websocket_mask = _websocket_mask_python -else: - try: - from ._websocket import _websocket_mask_cython # type: ignore - _websocket_mask = _websocket_mask_cython - except ImportError: # pragma: no cover - _websocket_mask = _websocket_mask_python - -_WS_DEFLATE_TRAILING = bytes([0x00, 0x00, 0xff, 0xff]) - - -_WS_EXT_RE = re.compile(r'^(?:;\s*(?:' - r'(server_no_context_takeover)|' - r'(client_no_context_takeover)|' - r'(server_max_window_bits(?:=(\d+))?)|' - r'(client_max_window_bits(?:=(\d+))?)))*$') - -_WS_EXT_RE_SPLIT = re.compile(r'permessage-deflate([^,]+)?') - - -def ws_ext_parse(extstr: str, isserver: bool=False) -> Tuple[int, bool]: - if not extstr: - return 0, False - - compress = 0 - notakeover = False - for ext in _WS_EXT_RE_SPLIT.finditer(extstr): - defext = ext.group(1) - # Return compress = 15 when get `permessage-deflate` - if not defext: - compress = 15 - break - match = _WS_EXT_RE.match(defext) - if match: - compress = 15 - if isserver: - # Server never fail to detect compress handshake. - # Server does not need to send max wbit to client - if match.group(4): - compress = int(match.group(4)) - # Group3 must match if group4 matches - # Compress wbit 8 does not support in zlib - # If compress level not support, - # CONTINUE to next extension - if compress > 15 or compress < 9: - compress = 0 - continue - if match.group(1): - notakeover = True - # Ignore regex group 5 & 6 for client_max_window_bits - break - else: - if match.group(6): - compress = int(match.group(6)) - # Group5 must match if group6 matches - # Compress wbit 8 does not support in zlib - # If compress level not support, - # FAIL the parse progress - if compress > 15 or compress < 9: - raise WSHandshakeError('Invalid window size') - if match.group(2): - notakeover = True - # Ignore regex group 5 & 6 for client_max_window_bits - break - # Return Fail if client side and not match - elif not isserver: - raise WSHandshakeError('Extension for deflate not supported' + - ext.group(1)) - - return compress, notakeover - - -def ws_ext_gen(compress: int=15, isserver: bool=False, - server_notakeover: bool=False) -> str: - # client_notakeover=False not used for server - # compress wbit 8 does not support in zlib - if compress < 9 or compress > 15: - raise ValueError('Compress wbits must between 9 and 15, ' - 'zlib does not support wbits=8') - enabledext = ['permessage-deflate'] - if not isserver: - enabledext.append('client_max_window_bits') - - if compress < 15: - enabledext.append('server_max_window_bits=' + str(compress)) - if server_notakeover: - enabledext.append('server_no_context_takeover') - # if client_notakeover: - # enabledext.append('client_no_context_takeover') - return '; '.join(enabledext) - - -class WSParserState(IntEnum): - READ_HEADER = 1 - READ_PAYLOAD_LENGTH = 2 - READ_PAYLOAD_MASK = 3 - READ_PAYLOAD = 4 - - -class WebSocketReader: - - def __init__(self, queue: DataQueue[WSMessage], - max_msg_size: int, compress: bool=True) -> None: - self.queue = queue - self._max_msg_size = max_msg_size - - self._exc = None # type: Optional[BaseException] - self._partial = bytearray() - self._state = WSParserState.READ_HEADER - - self._opcode = None # type: Optional[int] - self._frame_fin = False - self._frame_opcode = None # type: Optional[int] - self._frame_payload = bytearray() - - self._tail = b'' - self._has_mask = False - self._frame_mask = None # type: Optional[bytes] - self._payload_length = 0 - self._payload_length_flag = 0 - self._compressed = None # type: Optional[bool] - self._decompressobj = None # type: Any # zlib.decompressobj actually - self._compress = compress - - def feed_eof(self) -> None: - self.queue.feed_eof() - - def feed_data(self, data: bytes) -> Tuple[bool, bytes]: - if self._exc: - return True, data - - try: - return self._feed_data(data) - except Exception as exc: - self._exc = exc - self.queue.set_exception(exc) - return True, b'' - - def _feed_data(self, data: bytes) -> Tuple[bool, bytes]: - for fin, opcode, payload, compressed in self.parse_frame(data): - if compressed and not self._decompressobj: - self._decompressobj = zlib.decompressobj(wbits=-zlib.MAX_WBITS) - if opcode == WSMsgType.CLOSE: - if len(payload) >= 2: - close_code = UNPACK_CLOSE_CODE(payload[:2])[0] - if (close_code < 3000 and - close_code not in ALLOWED_CLOSE_CODES): - raise WebSocketError( - WSCloseCode.PROTOCOL_ERROR, - 'Invalid close code: {}'.format(close_code)) - try: - close_message = payload[2:].decode('utf-8') - except UnicodeDecodeError as exc: - raise WebSocketError( - WSCloseCode.INVALID_TEXT, - 'Invalid UTF-8 text message') from exc - msg = WSMessage(WSMsgType.CLOSE, close_code, close_message) - elif payload: - raise WebSocketError( - WSCloseCode.PROTOCOL_ERROR, - 'Invalid close frame: {} {} {!r}'.format( - fin, opcode, payload)) - else: - msg = WSMessage(WSMsgType.CLOSE, 0, '') - - self.queue.feed_data(msg, 0) - - elif opcode == WSMsgType.PING: - self.queue.feed_data( - WSMessage(WSMsgType.PING, payload, ''), len(payload)) - - elif opcode == WSMsgType.PONG: - self.queue.feed_data( - WSMessage(WSMsgType.PONG, payload, ''), len(payload)) - - elif opcode not in ( - WSMsgType.TEXT, WSMsgType.BINARY) and self._opcode is None: - raise WebSocketError( - WSCloseCode.PROTOCOL_ERROR, - "Unexpected opcode={!r}".format(opcode)) - else: - # load text/binary - if not fin: - # got partial frame payload - if opcode != WSMsgType.CONTINUATION: - self._opcode = opcode - self._partial.extend(payload) - if (self._max_msg_size and - len(self._partial) >= self._max_msg_size): - raise WebSocketError( - WSCloseCode.MESSAGE_TOO_BIG, - "Message size {} exceeds limit {}".format( - len(self._partial), self._max_msg_size)) - else: - # previous frame was non finished - # we should get continuation opcode - if self._partial: - if opcode != WSMsgType.CONTINUATION: - raise WebSocketError( - WSCloseCode.PROTOCOL_ERROR, - 'The opcode in non-fin frame is expected ' - 'to be zero, got {!r}'.format(opcode)) - - if opcode == WSMsgType.CONTINUATION: - assert self._opcode is not None - opcode = self._opcode - self._opcode = None - - self._partial.extend(payload) - if (self._max_msg_size and - len(self._partial) >= self._max_msg_size): - raise WebSocketError( - WSCloseCode.MESSAGE_TOO_BIG, - "Message size {} exceeds limit {}".format( - len(self._partial), self._max_msg_size)) - - # Decompress process must to be done after all packets - # received. - if compressed: - self._partial.extend(_WS_DEFLATE_TRAILING) - payload_merged = self._decompressobj.decompress( - self._partial, self._max_msg_size) - if self._decompressobj.unconsumed_tail: - left = len(self._decompressobj.unconsumed_tail) - raise WebSocketError( - WSCloseCode.MESSAGE_TOO_BIG, - "Decompressed message size {} exceeds limit {}" - .format( - self._max_msg_size + left, - self._max_msg_size - ) - ) - else: - payload_merged = bytes(self._partial) - - self._partial.clear() - - if opcode == WSMsgType.TEXT: - try: - text = payload_merged.decode('utf-8') - self.queue.feed_data( - WSMessage(WSMsgType.TEXT, text, ''), len(text)) - except UnicodeDecodeError as exc: - raise WebSocketError( - WSCloseCode.INVALID_TEXT, - 'Invalid UTF-8 text message') from exc - else: - self.queue.feed_data( - WSMessage(WSMsgType.BINARY, payload_merged, ''), - len(payload_merged)) - - return False, b'' - - def parse_frame(self, buf: bytes) -> List[Tuple[bool, Optional[int], - bytearray, - Optional[bool]]]: - """Return the next frame from the socket.""" - frames = [] - if self._tail: - buf, self._tail = self._tail + buf, b'' - - start_pos = 0 - buf_length = len(buf) - - while True: - # read header - if self._state == WSParserState.READ_HEADER: - if buf_length - start_pos >= 2: - data = buf[start_pos:start_pos+2] - start_pos += 2 - first_byte, second_byte = data - - fin = (first_byte >> 7) & 1 - rsv1 = (first_byte >> 6) & 1 - rsv2 = (first_byte >> 5) & 1 - rsv3 = (first_byte >> 4) & 1 - opcode = first_byte & 0xf - - # frame-fin = %x0 ; more frames of this message follow - # / %x1 ; final frame of this message - # frame-rsv1 = %x0 ; - # 1 bit, MUST be 0 unless negotiated otherwise - # frame-rsv2 = %x0 ; - # 1 bit, MUST be 0 unless negotiated otherwise - # frame-rsv3 = %x0 ; - # 1 bit, MUST be 0 unless negotiated otherwise - # - # Remove rsv1 from this test for deflate development - if rsv2 or rsv3 or (rsv1 and not self._compress): - raise WebSocketError( - WSCloseCode.PROTOCOL_ERROR, - 'Received frame with non-zero reserved bits') - - if opcode > 0x7 and fin == 0: - raise WebSocketError( - WSCloseCode.PROTOCOL_ERROR, - 'Received fragmented control frame') - - has_mask = (second_byte >> 7) & 1 - length = second_byte & 0x7f - - # Control frames MUST have a payload - # length of 125 bytes or less - if opcode > 0x7 and length > 125: - raise WebSocketError( - WSCloseCode.PROTOCOL_ERROR, - 'Control frame payload cannot be ' - 'larger than 125 bytes') - - # Set compress status if last package is FIN - # OR set compress status if this is first fragment - # Raise error if not first fragment with rsv1 = 0x1 - if self._frame_fin or self._compressed is None: - self._compressed = True if rsv1 else False - elif rsv1: - raise WebSocketError( - WSCloseCode.PROTOCOL_ERROR, - 'Received frame with non-zero reserved bits') - - self._frame_fin = bool(fin) - self._frame_opcode = opcode - self._has_mask = bool(has_mask) - self._payload_length_flag = length - self._state = WSParserState.READ_PAYLOAD_LENGTH - else: - break - - # read payload length - if self._state == WSParserState.READ_PAYLOAD_LENGTH: - length = self._payload_length_flag - if length == 126: - if buf_length - start_pos >= 2: - data = buf[start_pos:start_pos+2] - start_pos += 2 - length = UNPACK_LEN2(data)[0] - self._payload_length = length - self._state = ( - WSParserState.READ_PAYLOAD_MASK - if self._has_mask - else WSParserState.READ_PAYLOAD) - else: - break - elif length > 126: - if buf_length - start_pos >= 8: - data = buf[start_pos:start_pos+8] - start_pos += 8 - length = UNPACK_LEN3(data)[0] - self._payload_length = length - self._state = ( - WSParserState.READ_PAYLOAD_MASK - if self._has_mask - else WSParserState.READ_PAYLOAD) - else: - break - else: - self._payload_length = length - self._state = ( - WSParserState.READ_PAYLOAD_MASK - if self._has_mask - else WSParserState.READ_PAYLOAD) - - # read payload mask - if self._state == WSParserState.READ_PAYLOAD_MASK: - if buf_length - start_pos >= 4: - self._frame_mask = buf[start_pos:start_pos+4] - start_pos += 4 - self._state = WSParserState.READ_PAYLOAD - else: - break - - if self._state == WSParserState.READ_PAYLOAD: - length = self._payload_length - payload = self._frame_payload - - chunk_len = buf_length - start_pos - if length >= chunk_len: - self._payload_length = length - chunk_len - payload.extend(buf[start_pos:]) - start_pos = buf_length - else: - self._payload_length = 0 - payload.extend(buf[start_pos:start_pos+length]) - start_pos = start_pos + length - - if self._payload_length == 0: - if self._has_mask: - assert self._frame_mask is not None - _websocket_mask(self._frame_mask, payload) - - frames.append(( - self._frame_fin, - self._frame_opcode, - payload, - self._compressed)) - - self._frame_payload = bytearray() - self._state = WSParserState.READ_HEADER - else: - break - - self._tail = buf[start_pos:] - - return frames - - -class WebSocketWriter: - - def __init__(self, protocol: BaseProtocol, transport: asyncio.Transport, *, - use_mask: bool=False, limit: int=DEFAULT_LIMIT, - random: Any=random.Random(), - compress: int=0, notakeover: bool=False) -> None: - self.protocol = protocol - self.transport = transport - self.use_mask = use_mask - self.randrange = random.randrange - self.compress = compress - self.notakeover = notakeover - self._closing = False - self._limit = limit - self._output_size = 0 - self._compressobj = None # type: Any # actually compressobj - - async def _send_frame(self, message: bytes, opcode: int, - compress: Optional[int]=None) -> None: - """Send a frame over the websocket with message as its payload.""" - if self._closing: - ws_logger.warning('websocket connection is closing.') - - rsv = 0 - - # Only compress larger packets (disabled) - # Does small packet needs to be compressed? - # if self.compress and opcode < 8 and len(message) > 124: - if (compress or self.compress) and opcode < 8: - if compress: - # Do not set self._compress if compressing is for this frame - compressobj = zlib.compressobj(wbits=-compress) - else: # self.compress - if not self._compressobj: - self._compressobj = zlib.compressobj(wbits=-self.compress) - compressobj = self._compressobj - - message = compressobj.compress(message) - message = message + compressobj.flush( - zlib.Z_FULL_FLUSH if self.notakeover else zlib.Z_SYNC_FLUSH) - if message.endswith(_WS_DEFLATE_TRAILING): - message = message[:-4] - rsv = rsv | 0x40 - - msg_length = len(message) - - use_mask = self.use_mask - if use_mask: - mask_bit = 0x80 - else: - mask_bit = 0 - - if msg_length < 126: - header = PACK_LEN1(0x80 | rsv | opcode, msg_length | mask_bit) - elif msg_length < (1 << 16): - header = PACK_LEN2(0x80 | rsv | opcode, 126 | mask_bit, msg_length) - else: - header = PACK_LEN3(0x80 | rsv | opcode, 127 | mask_bit, msg_length) - if use_mask: - mask = self.randrange(0, 0xffffffff) - mask = mask.to_bytes(4, 'big') - message = bytearray(message) - _websocket_mask(mask, message) - self.transport.write(header + mask + message) - self._output_size += len(header) + len(mask) + len(message) - else: - if len(message) > MSG_SIZE: - self.transport.write(header) - self.transport.write(message) - else: - self.transport.write(header + message) - - self._output_size += len(header) + len(message) - - if self._output_size > self._limit: - self._output_size = 0 - await self.protocol._drain_helper() - - async def pong(self, message: bytes=b'') -> None: - """Send pong message.""" - if isinstance(message, str): - message = message.encode('utf-8') - await self._send_frame(message, WSMsgType.PONG) - - async def ping(self, message: bytes=b'') -> None: - """Send ping message.""" - if isinstance(message, str): - message = message.encode('utf-8') - await self._send_frame(message, WSMsgType.PING) - - async def send(self, message: Union[str, bytes], - binary: bool=False, - compress: Optional[int]=None) -> None: - """Send a frame over the websocket with message as its payload.""" - if isinstance(message, str): - message = message.encode('utf-8') - if binary: - await self._send_frame(message, WSMsgType.BINARY, compress) - else: - await self._send_frame(message, WSMsgType.TEXT, compress) - - async def close(self, code: int=1000, message: bytes=b'') -> None: - """Close the websocket, sending the specified code and message.""" - if isinstance(message, str): - message = message.encode('utf-8') - try: - await self._send_frame( - PACK_CLOSE_CODE(code) + message, opcode=WSMsgType.CLOSE) - finally: - self._closing = True diff --git a/venv/Lib/site-packages/aiohttp/http_writer.py b/venv/Lib/site-packages/aiohttp/http_writer.py deleted file mode 100644 index 7e27fbf6..00000000 --- a/venv/Lib/site-packages/aiohttp/http_writer.py +++ /dev/null @@ -1,172 +0,0 @@ -"""Http related parsers and protocol.""" - -import asyncio -import collections -import zlib -from typing import Any, Awaitable, Callable, Optional, Union # noqa - -from multidict import CIMultiDict # noqa - -from .abc import AbstractStreamWriter -from .base_protocol import BaseProtocol -from .helpers import NO_EXTENSIONS - -__all__ = ('StreamWriter', 'HttpVersion', 'HttpVersion10', 'HttpVersion11') - -HttpVersion = collections.namedtuple('HttpVersion', ['major', 'minor']) -HttpVersion10 = HttpVersion(1, 0) -HttpVersion11 = HttpVersion(1, 1) - - -_T_OnChunkSent = Optional[Callable[[bytes], Awaitable[None]]] - - -class StreamWriter(AbstractStreamWriter): - - def __init__(self, - protocol: BaseProtocol, - loop: asyncio.AbstractEventLoop, - on_chunk_sent: _T_OnChunkSent = None) -> None: - self._protocol = protocol - self._transport = protocol.transport - - self.loop = loop - self.length = None - self.chunked = False - self.buffer_size = 0 - self.output_size = 0 - - self._eof = False - self._compress = None # type: Any - self._drain_waiter = None - - self._on_chunk_sent = on_chunk_sent # type: _T_OnChunkSent - - @property - def transport(self) -> Optional[asyncio.Transport]: - return self._transport - - @property - def protocol(self) -> BaseProtocol: - return self._protocol - - def enable_chunking(self) -> None: - self.chunked = True - - def enable_compression(self, encoding: str='deflate') -> None: - zlib_mode = (16 + zlib.MAX_WBITS - if encoding == 'gzip' else -zlib.MAX_WBITS) - self._compress = zlib.compressobj(wbits=zlib_mode) - - def _write(self, chunk: bytes) -> None: - size = len(chunk) - self.buffer_size += size - self.output_size += size - - if self._transport is None or self._transport.is_closing(): - raise ConnectionResetError('Cannot write to closing transport') - self._transport.write(chunk) - - async def write(self, chunk: bytes, - *, drain: bool=True, LIMIT: int=0x10000) -> None: - """Writes chunk of data to a stream. - - write_eof() indicates end of stream. - writer can't be used after write_eof() method being called. - write() return drain future. - """ - if self._on_chunk_sent is not None: - await self._on_chunk_sent(chunk) - - if self._compress is not None: - chunk = self._compress.compress(chunk) - if not chunk: - return - - if self.length is not None: - chunk_len = len(chunk) - if self.length >= chunk_len: - self.length = self.length - chunk_len - else: - chunk = chunk[:self.length] - self.length = 0 - if not chunk: - return - - if chunk: - if self.chunked: - chunk_len_pre = ('%x\r\n' % len(chunk)).encode('ascii') - chunk = chunk_len_pre + chunk + b'\r\n' - - self._write(chunk) - - if self.buffer_size > LIMIT and drain: - self.buffer_size = 0 - await self.drain() - - async def write_headers(self, status_line: str, - headers: 'CIMultiDict[str]') -> None: - """Write request/response status and headers.""" - # status + headers - buf = _serialize_headers(status_line, headers) - self._write(buf) - - async def write_eof(self, chunk: bytes=b'') -> None: - if self._eof: - return - - if chunk and self._on_chunk_sent is not None: - await self._on_chunk_sent(chunk) - - if self._compress: - if chunk: - chunk = self._compress.compress(chunk) - - chunk = chunk + self._compress.flush() - if chunk and self.chunked: - chunk_len = ('%x\r\n' % len(chunk)).encode('ascii') - chunk = chunk_len + chunk + b'\r\n0\r\n\r\n' - else: - if self.chunked: - if chunk: - chunk_len = ('%x\r\n' % len(chunk)).encode('ascii') - chunk = chunk_len + chunk + b'\r\n0\r\n\r\n' - else: - chunk = b'0\r\n\r\n' - - if chunk: - self._write(chunk) - - await self.drain() - - self._eof = True - self._transport = None - - async def drain(self) -> None: - """Flush the write buffer. - - The intended use is to write - - await w.write(data) - await w.drain() - """ - if self._protocol.transport is not None: - await self._protocol._drain_helper() - - -def _py_serialize_headers(status_line: str, - headers: 'CIMultiDict[str]') -> bytes: - line = status_line + '\r\n' + ''.join( - [k + ': ' + v + '\r\n' for k, v in headers.items()]) - return line.encode('utf-8') + b'\r\n' - - -_serialize_headers = _py_serialize_headers - -try: - import aiohttp._http_writer as _http_writer # type: ignore - _c_serialize_headers = _http_writer._serialize_headers - if not NO_EXTENSIONS: - _serialize_headers = _c_serialize_headers -except ImportError: - pass diff --git a/venv/Lib/site-packages/aiohttp/locks.py b/venv/Lib/site-packages/aiohttp/locks.py deleted file mode 100644 index ed41f979..00000000 --- a/venv/Lib/site-packages/aiohttp/locks.py +++ /dev/null @@ -1,44 +0,0 @@ -import asyncio -import collections -from typing import Any, Optional - -try: - from typing import Deque -except ImportError: - from typing_extensions import Deque # noqa - - -class EventResultOrError: - """ - This class wrappers the Event asyncio lock allowing either awake the - locked Tasks without any error or raising an exception. - - thanks to @vorpalsmith for the simple design. - """ - def __init__(self, loop: asyncio.AbstractEventLoop) -> None: - self._loop = loop - self._exc = None # type: Optional[BaseException] - self._event = asyncio.Event(loop=loop) - self._waiters = collections.deque() # type: Deque[asyncio.Future[Any]] - - def set(self, exc: Optional[BaseException]=None) -> None: - self._exc = exc - self._event.set() - - async def wait(self) -> Any: - waiter = self._loop.create_task(self._event.wait()) - self._waiters.append(waiter) - try: - val = await waiter - finally: - self._waiters.remove(waiter) - - if self._exc is not None: - raise self._exc - - return val - - def cancel(self) -> None: - """ Cancel all waiters """ - for waiter in self._waiters: - waiter.cancel() diff --git a/venv/Lib/site-packages/aiohttp/multipart.py b/venv/Lib/site-packages/aiohttp/multipart.py index c4a2d1d9..093c8560 100644 --- a/venv/Lib/site-packages/aiohttp/multipart.py +++ b/venv/Lib/site-packages/aiohttp/multipart.py @@ -1,56 +1,40 @@ +import asyncio import base64 import binascii +import io import json +import mimetypes +import os import re +import sys import uuid import warnings import zlib -from collections import deque -from types import TracebackType -from typing import ( # noqa - TYPE_CHECKING, - Any, - Dict, - Iterator, - List, - Mapping, - Optional, - Sequence, - Tuple, - Type, - Union, -) -from urllib.parse import parse_qsl, unquote, urlencode - -from multidict import CIMultiDict, CIMultiDictProxy, MultiMapping # noqa - -from .hdrs import ( - CONTENT_DISPOSITION, - CONTENT_ENCODING, - CONTENT_LENGTH, - CONTENT_TRANSFER_ENCODING, - CONTENT_TYPE, -) -from .helpers import CHAR, TOKEN, parse_mimetype, reify -from .http import HeadersParser -from .payload import ( - JsonPayload, - LookupError, - Order, - Payload, - StringPayload, - get_payload, - payload_type, -) -from .streams import StreamReader - -__all__ = ('MultipartReader', 'MultipartWriter', 'BodyPartReader', +from collections import Mapping, Sequence, deque +from pathlib import Path +from urllib.parse import parse_qsl, quote, unquote, urlencode + +from multidict import CIMultiDict + +from .hdrs import (CONTENT_DISPOSITION, CONTENT_ENCODING, CONTENT_LENGTH, + CONTENT_TRANSFER_ENCODING, CONTENT_TYPE) +from .helpers import parse_mimetype +from .protocol import HttpParser + +__all__ = ('MultipartReader', 'MultipartWriter', + 'BodyPartReader', 'BodyPartWriter', 'BadContentDispositionHeader', 'BadContentDispositionParam', 'parse_content_disposition', 'content_disposition_filename') -if TYPE_CHECKING: # pragma: no cover - from .client_reqrep import ClientResponse # noqa +CHAR = set(chr(i) for i in range(0, 128)) +CTL = set(chr(i) for i in range(0, 32)) | {chr(127), } +SEPARATORS = {'(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', + '?', '=', '{', '}', ' ', chr(9)} +TOKEN = CHAR ^ CTL ^ SEPARATORS + +PY_35 = sys.version_info >= (3, 5) +PY_352 = sys.version_info >= (3, 5, 2) class BadContentDispositionHeader(RuntimeWarning): @@ -61,30 +45,27 @@ class BadContentDispositionParam(RuntimeWarning): pass -def parse_content_disposition(header: Optional[str]) -> Tuple[Optional[str], - Dict[str, str]]: - - def is_token(string: str) -> bool: - return bool(string) and TOKEN >= set(string) +def parse_content_disposition(header): + def is_token(string): + return string and TOKEN >= set(string) - def is_quoted(string: str) -> bool: + def is_quoted(string): return string[0] == string[-1] == '"' - def is_rfc5987(string: str) -> bool: + def is_rfc5987(string): return is_token(string) and string.count("'") == 2 - def is_extended_param(string: str) -> bool: + def is_extended_param(string): return string.endswith('*') - def is_continuous_param(string: str) -> bool: + def is_continuous_param(string): pos = string.find('*') + 1 if not pos: return False substring = string[pos:-1] if string.endswith('*') else string[pos:] return substring.isdigit() - def unescape(text: str, *, - chars: str=''.join(map(re.escape, CHAR))) -> str: + def unescape(text, *, chars=''.join(map(re.escape, CHAR))): return re.sub('\\\\([{}])'.format(chars), '\\1', text) if not header: @@ -95,10 +76,8 @@ def parse_content_disposition(header: Optional[str]) -> Tuple[Optional[str], warnings.warn(BadContentDispositionHeader(header)) return None, {} - params = {} # type: Dict[str, str] - while parts: - item = parts.pop(0) - + params = {} + for item in parts: if '=' not in item: warnings.warn(BadContentDispositionHeader(header)) return None, {} @@ -137,22 +116,9 @@ def parse_content_disposition(header: Optional[str]) -> Tuple[Optional[str], continue else: - failed = True if is_quoted(value): - failed = False value = unescape(value[1:-1].lstrip('\\/')) - elif is_token(value): - failed = False - elif parts: - # maybe just ; in filename, in any case this is just - # one case fix, for proper fix we need to redesign parser - _value = '%s;%s' % (value, parts[0]) - if is_quoted(_value): - parts.pop(0) - value = unescape(_value[1:-1].lstrip('\\/')) - failed = False - - if failed: + elif not is_token(value): warnings.warn(BadContentDispositionHeader(header)) return None, {} @@ -161,20 +127,18 @@ def parse_content_disposition(header: Optional[str]) -> Tuple[Optional[str], return disptype.lower(), params -def content_disposition_filename(params: Mapping[str, str], - name: str='filename') -> Optional[str]: - name_suf = '%s*' % name +def content_disposition_filename(params): if not params: return None - elif name_suf in params: - return params[name_suf] - elif name in params: - return params[name] + elif 'filename*' in params: + return params['filename*'] + elif 'filename' in params: + return params['filename'] else: parts = [] fnparams = sorted((key, value) for key, value in params.items() - if key.startswith(name_suf)) + if key.startswith('filename*')) for num, (key, value) in enumerate(fnparams): _, tail = key.split('*', 1) if tail.endswith('*'): @@ -193,59 +157,56 @@ def content_disposition_filename(params: Mapping[str, str], return value -class MultipartResponseWrapper: - """Wrapper around the MultipartReader. - - It takes care about - underlying connection and close it when it needs in. - """ +class MultipartResponseWrapper(object): + """Wrapper around the :class:`MultipartBodyReader` to take care about + underlying connection and close it when it needs in.""" - def __init__( - self, - resp: 'ClientResponse', - stream: 'MultipartReader', - ) -> None: + def __init__(self, resp, stream): self.resp = resp self.stream = stream - def __aiter__(self) -> 'MultipartResponseWrapper': - return self + if PY_35: + def __aiter__(self): + return self + + if not PY_352: # pragma: no cover + __aiter__ = asyncio.coroutine(__aiter__) + + @asyncio.coroutine + def __anext__(self): + part = yield from self.next() + if part is None: + raise StopAsyncIteration # NOQA + return part - async def __anext__( - self, - ) -> Union['MultipartReader', 'BodyPartReader']: - part = await self.next() - if part is None: - raise StopAsyncIteration # NOQA - return part + def at_eof(self): + """Returns ``True`` when all response data had been read. - def at_eof(self) -> bool: - """Returns True when all response data had been read.""" + :rtype: bool + """ return self.resp.content.at_eof() - async def next( - self, - ) -> Optional[Union['MultipartReader', 'BodyPartReader']]: + @asyncio.coroutine + def next(self): """Emits next multipart reader object.""" - item = await self.stream.next() + item = yield from self.stream.next() if self.stream.at_eof(): - await self.release() + yield from self.release() return item - async def release(self) -> None: + @asyncio.coroutine + def release(self): """Releases the connection gracefully, reading all the content to the void.""" - await self.resp.release() + yield from self.resp.release() -class BodyPartReader: +class BodyPartReader(object): """Multipart reader for single body part.""" chunk_size = 8192 - def __init__(self, boundary: bytes, - headers: 'CIMultiDictProxy[str]', - content: StreamReader) -> None: + def __init__(self, boundary, headers, content): self.headers = headers self._boundary = boundary self._content = content @@ -253,86 +214,110 @@ class BodyPartReader: length = self.headers.get(CONTENT_LENGTH, None) self._length = int(length) if length is not None else None self._read_bytes = 0 - # TODO: typeing.Deque is not supported by Python 3.5 - self._unread = deque() # type: Any - self._prev_chunk = None # type: Optional[bytes] + self._unread = deque() + self._prev_chunk = None self._content_eof = 0 - self._cache = {} # type: Dict[str, Any] - def __aiter__(self) -> 'BodyPartReader': - return self + if PY_35: + def __aiter__(self): + return self + + if not PY_352: # pragma: no cover + __aiter__ = asyncio.coroutine(__aiter__) - async def __anext__(self) -> bytes: - part = await self.next() - if part is None: - raise StopAsyncIteration # NOQA - return part + @asyncio.coroutine + def __anext__(self): + part = yield from self.next() + if part is None: + raise StopAsyncIteration # NOQA + return part - async def next(self) -> Optional[bytes]: - item = await self.read() + @asyncio.coroutine + def next(self): + item = yield from self.read() if not item: return None return item - async def read(self, *, decode: bool=False) -> bytes: + @asyncio.coroutine + def read(self, *, decode=False): """Reads body part data. - decode: Decodes data following by encoding - method from Content-Encoding header. If it missed - data remains untouched + :param bool decode: Decodes data following by encoding + method from `Content-Encoding` header. If it missed + data remains untouched + + :rtype: bytearray """ if self._at_eof: return b'' data = bytearray() - while not self._at_eof: - data.extend((await self.read_chunk(self.chunk_size))) + if self._length is None: + while not self._at_eof: + data.extend((yield from self.readline())) + else: + while not self._at_eof: + data.extend((yield from self.read_chunk(self.chunk_size))) if decode: return self.decode(data) return data - async def read_chunk(self, size: int=chunk_size) -> bytes: + @asyncio.coroutine + def read_chunk(self, size=chunk_size): """Reads body part content chunk of the specified size. - size: chunk size + :param int size: chunk size + + :rtype: bytearray """ if self._at_eof: return b'' if self._length: - chunk = await self._read_chunk_from_length(size) + chunk = yield from self._read_chunk_from_length(size) else: - chunk = await self._read_chunk_from_stream(size) + chunk = yield from self._read_chunk_from_stream(size) self._read_bytes += len(chunk) if self._read_bytes == self._length: self._at_eof = True if self._at_eof: - clrf = await self._content.readline() - assert b'\r\n' == clrf, \ + assert b'\r\n' == (yield from self._content.readline()), \ 'reader did not read all the data or it is malformed' return chunk - async def _read_chunk_from_length(self, size: int) -> bytes: - # Reads body part content chunk of the specified size. - # The body part must has Content-Length header with proper value. + @asyncio.coroutine + def _read_chunk_from_length(self, size): + """Reads body part content chunk of the specified size. + The body part must has `Content-Length` header with proper value. + + :param int size: chunk size + + :rtype: bytearray + """ assert self._length is not None, \ 'Content-Length required for chunked read' chunk_size = min(size, self._length - self._read_bytes) - chunk = await self._content.read(chunk_size) + chunk = yield from self._content.read(chunk_size) return chunk - async def _read_chunk_from_stream(self, size: int) -> bytes: - # Reads content chunk of body part with unknown length. - # The Content-Length header for body part is not necessary. + @asyncio.coroutine + def _read_chunk_from_stream(self, size): + """Reads content chunk of body part with unknown length. + The `Content-Length` header for body part is not necessary. + + :param int size: chunk size + + :rtype: bytearray + """ assert size >= len(self._boundary) + 2, \ 'Chunk size must be greater or equal than boundary length + 2' first_chunk = self._prev_chunk is None if first_chunk: - self._prev_chunk = await self._content.read(size) + self._prev_chunk = yield from self._content.read(size) - chunk = await self._content.read(size) + chunk = yield from self._content.read(size) self._content_eof += int(self._content.at_eof()) assert self._content_eof < 3, "Reading after EOF" - assert self._prev_chunk is not None window = self._prev_chunk + chunk sub = b'\r\n' + self._boundary if first_chunk: @@ -341,28 +326,33 @@ class BodyPartReader: idx = window.find(sub, max(0, len(self._prev_chunk) - len(sub))) if idx >= 0: # pushing boundary back to content - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", - category=DeprecationWarning) - self._content.unread_data(window[idx:]) + self._content.unread_data(window[idx:]) if size > idx: self._prev_chunk = self._prev_chunk[:idx] chunk = window[len(self._prev_chunk):idx] if not chunk: self._at_eof = True + if 0 < len(chunk) < len(sub) and not self._content_eof: + self._prev_chunk += chunk + self._at_eof = False + return b'' result = self._prev_chunk self._prev_chunk = chunk return result - async def readline(self) -> bytes: - """Reads body part by line by line.""" + @asyncio.coroutine + def readline(self): + """Reads body part by line by line. + + :rtype: bytearray + """ if self._at_eof: return b'' if self._unread: line = self._unread.popleft() else: - line = await self._content.readline() + line = yield from self._content.readline() if line.startswith(self._boundary): # the very last boundary may not come with \r\n, @@ -376,61 +366,91 @@ class BodyPartReader: self._unread.append(line) return b'' else: - next_line = await self._content.readline() + next_line = yield from self._content.readline() if next_line.startswith(self._boundary): line = line[:-2] # strip CRLF but only once self._unread.append(next_line) return line - async def release(self) -> None: - """Like read(), but reads all the data to the void.""" + @asyncio.coroutine + def release(self): + """Like :meth:`read`, but reads all the data to the void. + + :rtype: None + """ if self._at_eof: return - while not self._at_eof: - await self.read_chunk(self.chunk_size) + if self._length is None: + while not self._at_eof: + yield from self.readline() + else: + while not self._at_eof: + yield from self.read_chunk(self.chunk_size) - async def text(self, *, encoding: Optional[str]=None) -> str: - """Like read(), but assumes that body part contains text data.""" - data = await self.read(decode=True) - # see https://www.w3.org/TR/html5/forms.html#multipart/form-data-encoding-algorithm # NOQA - # and https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#dom-xmlhttprequest-send # NOQA - encoding = encoding or self.get_charset(default='utf-8') + @asyncio.coroutine + def text(self, *, encoding=None): + """Like :meth:`read`, but assumes that body part contains text data. + + :param str encoding: Custom text encoding. Overrides specified + in charset param of `Content-Type` header + + :rtype: str + """ + data = yield from self.read(decode=True) + encoding = encoding or self.get_charset(default='latin1') return data.decode(encoding) - async def json(self, - *, - encoding: Optional[str]=None) -> Optional[Dict[str, Any]]: - """Like read(), but assumes that body parts contains JSON data.""" - data = await self.read(decode=True) + @asyncio.coroutine + def json(self, *, encoding=None): + """Like :meth:`read`, but assumes that body parts contains JSON data. + + :param str encoding: Custom JSON encoding. Overrides specified + in charset param of `Content-Type` header + """ + data = yield from self.read(decode=True) if not data: return None encoding = encoding or self.get_charset(default='utf-8') return json.loads(data.decode(encoding)) - async def form(self, *, - encoding: Optional[str]=None) -> List[Tuple[str, str]]: - """Like read(), but assumes that body parts contains form + @asyncio.coroutine + def form(self, *, encoding=None): + """Like :meth:`read`, but assumes that body parts contains form urlencoded data. + + :param str encoding: Custom form encoding. Overrides specified + in charset param of `Content-Type` header """ - data = await self.read(decode=True) + data = yield from self.read(decode=True) if not data: - return [] - if encoding is not None: - real_encoding = encoding - else: - real_encoding = self.get_charset(default='utf-8') - return parse_qsl(data.rstrip().decode(real_encoding), - keep_blank_values=True, - encoding=real_encoding) + return None + encoding = encoding or self.get_charset(default='utf-8') + return parse_qsl(data.rstrip().decode(encoding), encoding=encoding) + + def at_eof(self): + """Returns ``True`` if the boundary was reached or + ``False`` otherwise. - def at_eof(self) -> bool: - """Returns True if the boundary was reached or False otherwise.""" + :rtype: bool + """ return self._at_eof - def decode(self, data: bytes) -> bytes: - """Decodes data according the specified Content-Encoding - or Content-Transfer-Encoding headers value. + def decode(self, data): + """Decodes data according the specified `Content-Encoding` + or `Content-Transfer-Encoding` headers value. + + Supports ``gzip``, ``deflate`` and ``identity`` encodings for + `Content-Encoding` header. + + Supports ``base64``, ``quoted-printable``, ``binary`` encodings for + `Content-Transfer-Encoding` header. + + :param bytearray data: Data to decode. + + :raises: :exc:`RuntimeError` - if encoding is unknown. + + :rtype: bytes """ if CONTENT_TRANSFER_ENCODING in self.headers: data = self._decode_content_transfer(data) @@ -438,8 +458,8 @@ class BodyPartReader: return self._decode_content(data) return data - def _decode_content(self, data: bytes) -> bytes: - encoding = self.headers.get(CONTENT_ENCODING, '').lower() + def _decode_content(self, data): + encoding = self.headers[CONTENT_ENCODING].lower() if encoding == 'deflate': return zlib.decompress(data, -zlib.MAX_WBITS) @@ -450,70 +470,36 @@ class BodyPartReader: else: raise RuntimeError('unknown content encoding: {}'.format(encoding)) - def _decode_content_transfer(self, data: bytes) -> bytes: - encoding = self.headers.get(CONTENT_TRANSFER_ENCODING, '').lower() + def _decode_content_transfer(self, data): + encoding = self.headers[CONTENT_TRANSFER_ENCODING].lower() if encoding == 'base64': return base64.b64decode(data) elif encoding == 'quoted-printable': return binascii.a2b_qp(data) - elif encoding in ('binary', '8bit', '7bit'): + elif encoding == 'binary': return data else: raise RuntimeError('unknown content transfer encoding: {}' ''.format(encoding)) - def get_charset(self, default: str) -> str: - """Returns charset parameter from Content-Type header or default.""" - ctype = self.headers.get(CONTENT_TYPE, '') - mimetype = parse_mimetype(ctype) - return mimetype.parameters.get('charset', default) - - @reify - def name(self) -> Optional[str]: - """Returns name specified in Content-Disposition header or None - if missed or header is malformed. + def get_charset(self, default=None): + """Returns charset parameter from ``Content-Type`` header or default. """ + ctype = self.headers.get(CONTENT_TYPE, '') + *_, params = parse_mimetype(ctype) + return params.get('charset', default) + @property + def filename(self): + """Returns filename specified in Content-Disposition header or ``None`` + if missed or header is malformed.""" _, params = parse_content_disposition( self.headers.get(CONTENT_DISPOSITION)) - return content_disposition_filename(params, 'name') - - @reify - def filename(self) -> Optional[str]: - """Returns filename specified in Content-Disposition header or None - if missed or header is malformed. - """ - _, params = parse_content_disposition( - self.headers.get(CONTENT_DISPOSITION)) - return content_disposition_filename(params, 'filename') - - -@payload_type(BodyPartReader, order=Order.try_first) -class BodyPartReaderPayload(Payload): - - def __init__(self, value: BodyPartReader, - *args: Any, **kwargs: Any) -> None: - super().__init__(value, *args, **kwargs) - - params = {} # type: Dict[str, str] - if value.name is not None: - params['name'] = value.name - if value.filename is not None: - params['filename'] = value.filename - - if params: - self.set_content_disposition('attachment', True, **params) - - async def write(self, writer: Any) -> None: - field = self._value - chunk = await field.read_chunk(size=2**16) - while chunk: - await writer.write(field.decode(chunk)) - chunk = await field.read_chunk(size=2**16) + return content_disposition_filename(params) -class MultipartReader: +class MultipartReader(object): """Multipart body reader.""" #: Response wrapper, used when multipart readers constructs from response. @@ -524,32 +510,31 @@ class MultipartReader: #: Body part reader class for non multipart/* content types. part_reader_cls = BodyPartReader - def __init__(self, headers: Mapping[str, str], - content: StreamReader) -> None: + def __init__(self, headers, content): self.headers = headers self._boundary = ('--' + self._get_boundary()).encode() self._content = content - self._last_part = None # type: Optional[Union['MultipartReader', BodyPartReader]] # noqa + self._last_part = None self._at_eof = False self._at_bof = True - self._unread = [] # type: List[bytes] + self._unread = [] - def __aiter__(self) -> 'MultipartReader': - return self + if PY_35: + def __aiter__(self): + return self + + if not PY_352: # pragma: no cover + __aiter__ = asyncio.coroutine(__aiter__) - async def __anext__( - self, - ) -> Union['MultipartReader', BodyPartReader]: - part = await self.next() - if part is None: - raise StopAsyncIteration # NOQA - return part + @asyncio.coroutine + def __anext__(self): + part = yield from self.next() + if part is None: + raise StopAsyncIteration # NOQA + return part @classmethod - def from_response( - cls, - response: 'ClientResponse', - ) -> MultipartResponseWrapper: + def from_response(cls, response): """Constructs reader instance from HTTP response. :param response: :class:`~aiohttp.client.ClientResponse` instance @@ -558,90 +543,87 @@ class MultipartReader: response.content)) return obj - def at_eof(self) -> bool: - """Returns True if the final boundary was reached or - False otherwise. + def at_eof(self): + """Returns ``True`` if the final boundary was reached or + ``False`` otherwise. + + :rtype: bool """ return self._at_eof - async def next( - self, - ) -> Optional[Union['MultipartReader', BodyPartReader]]: + @asyncio.coroutine + def next(self): """Emits the next multipart body part.""" # So, if we're at BOF, we need to skip till the boundary. if self._at_eof: - return None - await self._maybe_release_last_part() + return + yield from self._maybe_release_last_part() if self._at_bof: - await self._read_until_first_boundary() + yield from self._read_until_first_boundary() self._at_bof = False else: - await self._read_boundary() + yield from self._read_boundary() if self._at_eof: # we just read the last boundary, nothing to do there - return None - self._last_part = await self.fetch_next_part() + return + self._last_part = yield from self.fetch_next_part() return self._last_part - async def release(self) -> None: + @asyncio.coroutine + def release(self): """Reads all the body parts to the void till the final boundary.""" while not self._at_eof: - item = await self.next() + item = yield from self.next() if item is None: break - await item.release() + yield from item.release() - async def fetch_next_part( - self, - ) -> Union['MultipartReader', BodyPartReader]: + @asyncio.coroutine + def fetch_next_part(self): """Returns the next body part reader.""" - headers = await self._read_headers() + headers = yield from self._read_headers() return self._get_part_reader(headers) - def _get_part_reader( - self, - headers: 'CIMultiDictProxy[str]', - ) -> Union['MultipartReader', BodyPartReader]: + def _get_part_reader(self, headers): """Dispatches the response by the `Content-Type` header, returning suitable reader instance. :param dict headers: Response headers """ ctype = headers.get(CONTENT_TYPE, '') - mimetype = parse_mimetype(ctype) - - if mimetype.type == 'multipart': + mtype, *_ = parse_mimetype(ctype) + if mtype == 'multipart': if self.multipart_reader_cls is None: return type(self)(headers, self._content) return self.multipart_reader_cls(headers, self._content) else: return self.part_reader_cls(self._boundary, headers, self._content) - def _get_boundary(self) -> str: - mimetype = parse_mimetype(self.headers[CONTENT_TYPE]) + def _get_boundary(self): + mtype, *_, params = parse_mimetype(self.headers[CONTENT_TYPE]) - assert mimetype.type == 'multipart', ( - 'multipart/* content type expected' - ) + assert mtype == 'multipart', 'multipart/* content type expected' - if 'boundary' not in mimetype.parameters: + if 'boundary' not in params: raise ValueError('boundary missed for Content-Type: %s' % self.headers[CONTENT_TYPE]) - boundary = mimetype.parameters['boundary'] + boundary = params['boundary'] if len(boundary) > 70: raise ValueError('boundary %r is too long (70 chars max)' % boundary) return boundary - async def _readline(self) -> bytes: + @asyncio.coroutine + def _readline(self): if self._unread: return self._unread.pop() - return await self._content.readline() + return (yield from self._content.readline()) - async def _read_until_first_boundary(self) -> None: + @asyncio.coroutine + def _read_until_first_boundary(self): while True: - chunk = await self._readline() + chunk = yield from self._readline() if chunk == b'': raise ValueError("Could not find starting boundary %r" % (self._boundary)) @@ -652,308 +634,340 @@ class MultipartReader: self._at_eof = True return - async def _read_boundary(self) -> None: - chunk = (await self._readline()).rstrip() + @asyncio.coroutine + def _read_boundary(self): + chunk = (yield from self._readline()).rstrip() if chunk == self._boundary: pass elif chunk == self._boundary + b'--': self._at_eof = True - epilogue = await self._readline() - next_line = await self._readline() - - # the epilogue is expected and then either the end of input or the - # parent multipart boundary, if the parent boundary is found then - # it should be marked as unread and handed to the parent for - # processing - if next_line[:2] == b'--': - self._unread.append(next_line) - # otherwise the request is likely missing an epilogue and both - # lines should be passed to the parent for processing - # (this handles the old behavior gracefully) - else: - self._unread.extend([next_line, epilogue]) else: raise ValueError('Invalid boundary %r, expected %r' % (chunk, self._boundary)) - async def _read_headers(self) -> 'CIMultiDictProxy[str]': + @asyncio.coroutine + def _read_headers(self): lines = [b''] while True: - chunk = await self._content.readline() + chunk = yield from self._content.readline() chunk = chunk.strip() lines.append(chunk) if not chunk: break - parser = HeadersParser() - headers, raw_headers = parser.parse_headers(lines) + parser = HttpParser() + headers, *_ = parser.parse_headers(lines) return headers - async def _maybe_release_last_part(self) -> None: + @asyncio.coroutine + def _maybe_release_last_part(self): """Ensures that the last read body part is read completely.""" if self._last_part is not None: if not self._last_part.at_eof(): - await self._last_part.release() + yield from self._last_part.release() self._unread.extend(self._last_part._unread) self._last_part = None -_Part = Tuple[Payload, str, str] +class BodyPartWriter(object): + """Multipart writer for single body part.""" + def __init__(self, obj, headers=None, *, chunk_size=8192): + if headers is None: + headers = CIMultiDict() + elif not isinstance(headers, CIMultiDict): + headers = CIMultiDict(headers) -class MultipartWriter(Payload): - """Multipart body writer.""" + self.obj = obj + self.headers = headers + self._chunk_size = chunk_size + self._fill_headers_with_defaults() + + self._serialize_map = { + bytes: self._serialize_bytes, + str: self._serialize_str, + io.IOBase: self._serialize_io, + MultipartWriter: self._serialize_multipart, + ('application', 'json'): self._serialize_json, + ('application', 'x-www-form-urlencoded'): self._serialize_form + } + + def _fill_headers_with_defaults(self): + if CONTENT_TYPE not in self.headers: + content_type = self._guess_content_type(self.obj) + if content_type is not None: + self.headers[CONTENT_TYPE] = content_type + + if CONTENT_LENGTH not in self.headers: + content_length = self._guess_content_length(self.obj) + if content_length is not None: + self.headers[CONTENT_LENGTH] = str(content_length) + + if CONTENT_DISPOSITION not in self.headers: + filename = self._guess_filename(self.obj) + if filename is not None: + self.set_content_disposition('attachment', filename=filename) + + def _guess_content_length(self, obj): + if isinstance(obj, bytes): + return len(obj) + elif isinstance(obj, str): + *_, params = parse_mimetype(self.headers.get(CONTENT_TYPE)) + charset = params.get('charset', 'us-ascii') + return len(obj.encode(charset)) + elif isinstance(obj, io.StringIO): + *_, params = parse_mimetype(self.headers.get(CONTENT_TYPE)) + charset = params.get('charset', 'us-ascii') + return len(obj.getvalue().encode(charset)) - obj.tell() + elif isinstance(obj, io.BytesIO): + return len(obj.getvalue()) - obj.tell() + elif isinstance(obj, io.IOBase): + try: + return os.fstat(obj.fileno()).st_size - obj.tell() + except (AttributeError, OSError): + return None + else: + return None - def __init__(self, subtype: str='mixed', - boundary: Optional[str]=None) -> None: - boundary = boundary if boundary is not None else uuid.uuid4().hex - # The underlying Payload API demands a str (utf-8), not bytes, - # so we need to ensure we don't lose anything during conversion. - # As a result, require the boundary to be ASCII only. - # In both situations. + def _guess_content_type(self, obj, default='application/octet-stream'): + if hasattr(obj, 'name'): + name = getattr(obj, 'name') + return mimetypes.guess_type(name)[0] + elif isinstance(obj, (str, io.StringIO)): + return 'text/plain; charset=utf-8' + else: + return default - try: - self._boundary = boundary.encode('ascii') - except UnicodeEncodeError: - raise ValueError('boundary should contain ASCII only chars') \ - from None - ctype = ('multipart/{}; boundary={}' - .format(subtype, self._boundary_value)) + def _guess_filename(self, obj): + if isinstance(obj, io.IOBase): + name = getattr(obj, 'name', None) + if name is not None: + return Path(name).name - super().__init__(None, content_type=ctype) + def serialize(self): + """Yields byte chunks for body part.""" - self._parts = [] # type: List[_Part] # noqa + has_encoding = ( + CONTENT_ENCODING in self.headers and + self.headers[CONTENT_ENCODING] != 'identity' or + CONTENT_TRANSFER_ENCODING in self.headers + ) + if has_encoding: + # since we're following streaming approach which doesn't assumes + # any intermediate buffers, we cannot calculate real content length + # with the specified content encoding scheme. So, instead of lying + # about content length and cause reading issues, we have to strip + # this information. + self.headers.pop(CONTENT_LENGTH, None) + + if self.headers: + yield b'\r\n'.join( + b': '.join(map(lambda i: i.encode('latin1'), item)) + for item in self.headers.items() + ) + yield b'\r\n\r\n' + yield from self._maybe_encode_stream(self._serialize_obj()) + yield b'\r\n' + + def _serialize_obj(self): + obj = self.obj + mtype, stype, *_ = parse_mimetype(self.headers.get(CONTENT_TYPE)) + serializer = self._serialize_map.get((mtype, stype)) + if serializer is not None: + return serializer(obj) + + for key in self._serialize_map: + if not isinstance(key, tuple) and isinstance(obj, key): + return self._serialize_map[key](obj) + return self._serialize_default(obj) + + def _serialize_bytes(self, obj): + yield obj + + def _serialize_str(self, obj): + *_, params = parse_mimetype(self.headers.get(CONTENT_TYPE)) + yield obj.encode(params.get('charset', 'us-ascii')) + + def _serialize_io(self, obj): + while True: + chunk = obj.read(self._chunk_size) + if not chunk: + break + if isinstance(chunk, str): + yield from self._serialize_str(chunk) + else: + yield from self._serialize_bytes(chunk) - def __enter__(self) -> 'MultipartWriter': - return self + def _serialize_multipart(self, obj): + yield from obj.serialize() - def __exit__(self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType]) -> None: - pass + def _serialize_json(self, obj): + *_, params = parse_mimetype(self.headers.get(CONTENT_TYPE)) + yield json.dumps(obj).encode(params.get('charset', 'utf-8')) - def __iter__(self) -> Iterator[_Part]: - return iter(self._parts) + def _serialize_form(self, obj): + if isinstance(obj, Mapping): + obj = list(obj.items()) + return self._serialize_str(urlencode(obj, doseq=True)) - def __len__(self) -> int: - return len(self._parts) + def _serialize_default(self, obj): + raise TypeError('unknown body part type %r' % type(obj)) - def __bool__(self) -> bool: - return True + def _maybe_encode_stream(self, stream): + if CONTENT_ENCODING in self.headers: + stream = self._apply_content_encoding(stream) + if CONTENT_TRANSFER_ENCODING in self.headers: + stream = self._apply_content_transfer_encoding(stream) + yield from stream - _valid_tchar_regex = re.compile(br"\A[!#$%&'*+\-.^_`|~\w]+\Z") - _invalid_qdtext_char_regex = re.compile(br"[\x00-\x08\x0A-\x1F\x7F]") + def _apply_content_encoding(self, stream): + encoding = self.headers[CONTENT_ENCODING].lower() + if encoding == 'identity': + yield from stream + elif encoding in ('deflate', 'gzip'): + if encoding == 'gzip': + zlib_mode = 16 + zlib.MAX_WBITS + else: + zlib_mode = -zlib.MAX_WBITS + zcomp = zlib.compressobj(wbits=zlib_mode) + for chunk in stream: + yield zcomp.compress(chunk) + else: + yield zcomp.flush() + else: + raise RuntimeError('unknown content encoding: {}' + ''.format(encoding)) - @property - def _boundary_value(self) -> str: - """Wrap boundary parameter value in quotes, if necessary. + def _apply_content_transfer_encoding(self, stream): + encoding = self.headers[CONTENT_TRANSFER_ENCODING].lower() + if encoding == 'base64': + buffer = bytearray() + while True: + if buffer: + div, mod = divmod(len(buffer), 3) + chunk, buffer = buffer[:div * 3], buffer[div * 3:] + if chunk: + yield base64.b64encode(chunk) + chunk = next(stream, None) + if not chunk: + if buffer: + yield base64.b64encode(buffer[:]) + return + buffer.extend(chunk) + elif encoding == 'quoted-printable': + for chunk in stream: + yield binascii.b2a_qp(chunk) + elif encoding == 'binary': + yield from stream + else: + raise RuntimeError('unknown content transfer encoding: {}' + ''.format(encoding)) + + def set_content_disposition(self, disptype, **params): + """Sets ``Content-Disposition`` header. - Reads self.boundary and returns a unicode sting. + :param str disptype: Disposition type: inline, attachment, form-data. + Should be valid extension token (see RFC 2183) + :param dict params: Disposition params """ - # Refer to RFCs 7231, 7230, 5234. - # - # parameter = token "=" ( token / quoted-string ) - # token = 1*tchar - # quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE - # qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text - # obs-text = %x80-FF - # quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) - # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" - # / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" - # / DIGIT / ALPHA - # ; any VCHAR, except delimiters - # VCHAR = %x21-7E - value = self._boundary - if re.match(self._valid_tchar_regex, value): - return value.decode('ascii') # cannot fail - - if re.search(self._invalid_qdtext_char_regex, value): - raise ValueError("boundary value contains invalid characters") - - # escape %x5C and %x22 - quoted_value_content = value.replace(b'\\', b'\\\\') - quoted_value_content = quoted_value_content.replace(b'"', b'\\"') - - return '"' + quoted_value_content.decode('ascii') + '"' + if not disptype or not (TOKEN > set(disptype)): + raise ValueError('bad content disposition type {!r}' + ''.format(disptype)) + value = disptype + if params: + lparams = [] + for key, val in params.items(): + if not key or not (TOKEN > set(key)): + raise ValueError('bad content disposition parameter' + ' {!r}={!r}'.format(key, val)) + qval = quote(val, '') + lparams.append((key, '"%s"' % qval)) + if key == 'filename': + lparams.append(('filename*', "utf-8''" + qval)) + sparams = '; '.join('='.join(pair) for pair in lparams) + value = '; '.join((value, sparams)) + self.headers[CONTENT_DISPOSITION] = value @property - def boundary(self) -> str: - return self._boundary.decode('ascii') - - def append( - self, - obj: Any, - headers: Optional[MultiMapping[str]]=None - ) -> Payload: - if headers is None: - headers = CIMultiDict() - - if isinstance(obj, Payload): - obj.headers.update(headers) - return self.append_payload(obj) - else: - try: - payload = get_payload(obj, headers=headers) - except LookupError: - raise TypeError('Cannot create payload from %r' % obj) - else: - return self.append_payload(payload) - - def append_payload(self, payload: Payload) -> Payload: - """Adds a new body part to multipart writer.""" - # compression - encoding = payload.headers.get( - CONTENT_ENCODING, - '', - ).lower() # type: Optional[str] - if encoding and encoding not in ('deflate', 'gzip', 'identity'): - raise RuntimeError('unknown content encoding: {}'.format(encoding)) - if encoding == 'identity': - encoding = None - - # te encoding - te_encoding = payload.headers.get( - CONTENT_TRANSFER_ENCODING, - '', - ).lower() # type: Optional[str] - if te_encoding not in ('', 'base64', 'quoted-printable', 'binary'): - raise RuntimeError('unknown content transfer encoding: {}' - ''.format(te_encoding)) - if te_encoding == 'binary': - te_encoding = None - - # size - size = payload.size - if size is not None and not (encoding or te_encoding): - payload.headers[CONTENT_LENGTH] = str(size) - - self._parts.append((payload, encoding, te_encoding)) # type: ignore - return payload - - def append_json( - self, - obj: Any, - headers: Optional[MultiMapping[str]]=None - ) -> Payload: - """Helper to append JSON part.""" - if headers is None: - headers = CIMultiDict() - - return self.append_payload(JsonPayload(obj, headers=headers)) + def filename(self): + """Returns filename specified in Content-Disposition header or ``None`` + if missed.""" + _, params = parse_content_disposition( + self.headers.get(CONTENT_DISPOSITION)) + return content_disposition_filename(params) - def append_form( - self, - obj: Union[Sequence[Tuple[str, str]], - Mapping[str, str]], - headers: Optional[MultiMapping[str]]=None - ) -> Payload: - """Helper to append form urlencoded part.""" - assert isinstance(obj, (Sequence, Mapping)) - if headers is None: - headers = CIMultiDict() +class MultipartWriter(object): + """Multipart body writer.""" - if isinstance(obj, Mapping): - obj = list(obj.items()) - data = urlencode(obj, doseq=True) + #: Body part reader class for non multipart/* content types. + part_writer_cls = BodyPartWriter - return self.append_payload( - StringPayload(data, headers=headers, - content_type='application/x-www-form-urlencoded')) + def __init__(self, subtype='mixed', boundary=None): + boundary = boundary if boundary is not None else uuid.uuid4().hex + try: + boundary.encode('us-ascii') + except UnicodeEncodeError: + raise ValueError('boundary should contains ASCII only chars') + self.headers = CIMultiDict() + self.headers[CONTENT_TYPE] = 'multipart/{}; boundary="{}"'.format( + subtype, boundary + ) + self.parts = [] - @property - def size(self) -> Optional[int]: - """Size of the payload.""" - total = 0 - for part, encoding, te_encoding in self._parts: - if encoding or te_encoding or part.size is None: - return None + def __enter__(self): + return self - total += int( - 2 + len(self._boundary) + 2 + # b'--'+self._boundary+b'\r\n' - part.size + len(part._binary_headers) + - 2 # b'\r\n' - ) + def __exit__(self, exc_type, exc_val, exc_tb): + pass - total += 2 + len(self._boundary) + 4 # b'--'+self._boundary+b'--\r\n' - return total - - async def write(self, writer: Any, - close_boundary: bool=True) -> None: - """Write body.""" - for part, encoding, te_encoding in self._parts: - await writer.write(b'--' + self._boundary + b'\r\n') - await writer.write(part._binary_headers) - - if encoding or te_encoding: - w = MultipartPayloadWriter(writer) - if encoding: - w.enable_compression(encoding) - if te_encoding: - w.enable_encoding(te_encoding) - await part.write(w) # type: ignore - await w.write_eof() - else: - await part.write(writer) + def __iter__(self): + return iter(self.parts) - await writer.write(b'\r\n') + def __len__(self): + return len(self.parts) - if close_boundary: - await writer.write(b'--' + self._boundary + b'--\r\n') + @property + def boundary(self): + *_, params = parse_mimetype(self.headers.get(CONTENT_TYPE)) + return params['boundary'].encode('us-ascii') + def append(self, obj, headers=None): + """Adds a new body part to multipart writer.""" + if isinstance(obj, self.part_writer_cls): + if headers: + obj.headers.update(headers) + self.parts.append(obj) + else: + if not headers: + headers = CIMultiDict() + self.parts.append(self.part_writer_cls(obj, headers)) + return self.parts[-1] -class MultipartPayloadWriter: + def append_json(self, obj, headers=None): + """Helper to append JSON part.""" + if not headers: + headers = CIMultiDict() + headers[CONTENT_TYPE] = 'application/json' + return self.append(obj, headers) - def __init__(self, writer: Any) -> None: - self._writer = writer - self._encoding = None # type: Optional[str] - self._compress = None # type: Any - self._encoding_buffer = None # type: Optional[bytearray] + def append_form(self, obj, headers=None): + """Helper to append form urlencoded part.""" + if not headers: + headers = CIMultiDict() + headers[CONTENT_TYPE] = 'application/x-www-form-urlencoded' + assert isinstance(obj, (Sequence, Mapping)) + return self.append(obj, headers) - def enable_encoding(self, encoding: str) -> None: - if encoding == 'base64': - self._encoding = encoding - self._encoding_buffer = bytearray() - elif encoding == 'quoted-printable': - self._encoding = 'quoted-printable' - - def enable_compression(self, encoding: str='deflate') -> None: - zlib_mode = (16 + zlib.MAX_WBITS - if encoding == 'gzip' else -zlib.MAX_WBITS) - self._compress = zlib.compressobj(wbits=zlib_mode) - - async def write_eof(self) -> None: - if self._compress is not None: - chunk = self._compress.flush() - if chunk: - self._compress = None - await self.write(chunk) - - if self._encoding == 'base64': - if self._encoding_buffer: - await self._writer.write(base64.b64encode( - self._encoding_buffer)) - - async def write(self, chunk: bytes) -> None: - if self._compress is not None: - if chunk: - chunk = self._compress.compress(chunk) - if not chunk: - return + def serialize(self): + """Yields multipart byte chunks.""" + if not self.parts: + yield b'' + return - if self._encoding == 'base64': - buf = self._encoding_buffer - assert buf is not None - buf.extend(chunk) - - if buf: - div, mod = divmod(len(buf), 3) - enc_chunk, self._encoding_buffer = ( - buf[:div * 3], buf[div * 3:]) - if enc_chunk: - b64chunk = base64.b64encode(enc_chunk) - await self._writer.write(b64chunk) - elif self._encoding == 'quoted-printable': - await self._writer.write(binascii.b2a_qp(chunk)) + for part in self.parts: + yield b'--' + self.boundary + b'\r\n' + yield from part.serialize() else: - await self._writer.write(chunk) + yield b'--' + self.boundary + b'--\r\n' + + yield b'' diff --git a/venv/Lib/site-packages/aiohttp/parsers.py b/venv/Lib/site-packages/aiohttp/parsers.py new file mode 100644 index 00000000..3168cdaf --- /dev/null +++ b/venv/Lib/site-packages/aiohttp/parsers.py @@ -0,0 +1,495 @@ +"""Parser is a generator function (NOT coroutine). + +Parser receives data with generator's send() method and sends data to +destination DataQueue. Parser receives ParserBuffer and DataQueue objects +as a parameters of the parser call, all subsequent send() calls should +send bytes objects. Parser sends parsed `term` to destination buffer with +DataQueue.feed_data() method. DataQueue object should implement two methods. +feed_data() - parser uses this method to send parsed protocol data. +feed_eof() - parser uses this method for indication of end of parsing stream. +To indicate end of incoming data stream EofStream exception should be sent +into parser. Parser could throw exceptions. + +There are three stages: + + * Data flow chain: + + 1. Application creates StreamParser object for storing incoming data. + 2. StreamParser creates ParserBuffer as internal data buffer. + 3. Application create parser and set it into stream buffer: + + parser = HttpRequestParser() + data_queue = stream.set_parser(parser) + + 3. At this stage StreamParser creates DataQueue object and passes it + and internal buffer into parser as an arguments. + + def set_parser(self, parser): + output = DataQueue() + self.p = parser(output, self._input) + return output + + 4. Application waits data on output.read() + + while True: + msg = yield from output.read() + ... + + * Data flow: + + 1. asyncio's transport reads data from socket and sends data to protocol + with data_received() call. + 2. Protocol sends data to StreamParser with feed_data() call. + 3. StreamParser sends data into parser with generator's send() method. + 4. Parser processes incoming data and sends parsed data + to DataQueue with feed_data() + 5. Application received parsed data from DataQueue.read() + + * Eof: + + 1. StreamParser receives eof with feed_eof() call. + 2. StreamParser throws EofStream exception into parser. + 3. Then it unsets parser. + +_SocketSocketTransport -> + -> "protocol" -> StreamParser -> "parser" -> DataQueue <- "application" + +""" + +import asyncio +import asyncio.streams +import inspect +import socket + +from . import errors +from .streams import EofStream, FlowControlDataQueue + +__all__ = ('EofStream', 'StreamParser', 'StreamProtocol', + 'ParserBuffer', 'StreamWriter') + +DEFAULT_LIMIT = 2 ** 16 + +if hasattr(socket, 'TCP_CORK'): # pragma: no cover + CORK = socket.TCP_CORK +elif hasattr(socket, 'TCP_NOPUSH'): # pragma: no cover + CORK = socket.TCP_NOPUSH +else: # pragma: no cover + CORK = None + + +class StreamParser: + """StreamParser manages incoming bytes stream and protocol parsers. + + StreamParser uses ParserBuffer as internal buffer. + + set_parser() sets current parser, it creates DataQueue object + and sends ParserBuffer and DataQueue into parser generator. + + unset_parser() sends EofStream into parser and then removes it. + """ + + def __init__(self, *, loop=None, buf=None, + limit=DEFAULT_LIMIT, eof_exc_class=RuntimeError, **kwargs): + self._loop = loop + self._eof = False + self._exception = None + self._parser = None + self._output = None + self._limit = limit + self._eof_exc_class = eof_exc_class + self._buffer = buf if buf is not None else ParserBuffer() + + self.paused = False + self.transport = None + + @property + def output(self): + return self._output + + def set_transport(self, transport): + assert transport is None or self.transport is None, \ + 'Transport already set' + self.transport = transport + + def at_eof(self): + return self._eof + + def exception(self): + return self._exception + + def set_exception(self, exc): + if isinstance(exc, ConnectionError): + exc, old_exc = self._eof_exc_class(), exc + exc.__cause__ = old_exc + exc.__context__ = old_exc + + self._exception = exc + + if self._output is not None: + self._output.set_exception(exc) + self._output = None + self._parser = None + + def feed_data(self, data): + """send data to current parser or store in buffer.""" + if data is None: + return + + if self._parser: + try: + self._parser.send(data) + except StopIteration: + self._output.feed_eof() + self._output = None + self._parser = None + except Exception as exc: + self._output.set_exception(exc) + self._output = None + self._parser = None + else: + self._buffer.feed_data(data) + + def feed_eof(self): + """send eof to all parsers, recursively.""" + if self._parser: + try: + if self._buffer: + self._parser.send(b'') + self._parser.throw(EofStream()) + except StopIteration: + self._output.feed_eof() + except EofStream: + self._output.set_exception(self._eof_exc_class()) + except Exception as exc: + self._output.set_exception(exc) + + self._parser = None + self._output = None + + self._eof = True + + def set_parser(self, parser, output=None): + """set parser to stream. return parser's DataQueue.""" + if self._parser: + self.unset_parser() + + if output is None: + output = FlowControlDataQueue( + self, limit=self._limit, loop=self._loop) + + if self._exception: + output.set_exception(self._exception) + return output + + # init parser + p = parser(output, self._buffer) + assert inspect.isgenerator(p), 'Generator is required' + + try: + # initialize parser with data and parser buffers + next(p) + except StopIteration: + pass + except Exception as exc: + output.set_exception(exc) + else: + # parser still require more data + self._parser = p + self._output = output + + if self._eof: + self.unset_parser() + + return output + + def unset_parser(self): + """unset parser, send eof to the parser and then remove it.""" + if self._parser is None: + return + + # TODO: write test + if self._loop.is_closed(): + # TODO: log something + return + + try: + self._parser.throw(EofStream()) + except StopIteration: + self._output.feed_eof() + except EofStream: + self._output.set_exception(self._eof_exc_class()) + except Exception as exc: + self._output.set_exception(exc) + finally: + self._output = None + self._parser = None + + +class StreamWriter(asyncio.streams.StreamWriter): + + def __init__(self, transport, protocol, reader, loop): + self._transport = transport + self._protocol = protocol + self._reader = reader + self._loop = loop + self._tcp_nodelay = False + self._tcp_cork = False + self._socket = transport.get_extra_info('socket') + + @property + def tcp_nodelay(self): + return self._tcp_nodelay + + def set_tcp_nodelay(self, value): + value = bool(value) + if self._tcp_nodelay == value: + return + self._tcp_nodelay = value + if self._socket is None: + return + if self._socket.family not in (socket.AF_INET, socket.AF_INET6): + return + if self._tcp_cork: + self._tcp_cork = False + if CORK is not None: # pragma: no branch + self._socket.setsockopt(socket.IPPROTO_TCP, CORK, False) + self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, value) + + @property + def tcp_cork(self): + return self._tcp_cork + + def set_tcp_cork(self, value): + value = bool(value) + if self._tcp_cork == value: + return + self._tcp_cork = value + if self._socket is None: + return + if self._socket.family not in (socket.AF_INET, socket.AF_INET6): + return + if self._tcp_nodelay: + self._socket.setsockopt(socket.IPPROTO_TCP, + socket.TCP_NODELAY, + False) + self._tcp_nodelay = False + if CORK is not None: # pragma: no branch + self._socket.setsockopt(socket.IPPROTO_TCP, CORK, value) + + +class StreamProtocol(asyncio.streams.FlowControlMixin, asyncio.Protocol): + """Helper class to adapt between Protocol and StreamReader.""" + + def __init__(self, *, loop=None, disconnect_error=RuntimeError, **kwargs): + super().__init__(loop=loop) + + self.transport = None + self.writer = None + self.reader = StreamParser( + loop=loop, eof_exc_class=disconnect_error, **kwargs) + + def is_connected(self): + return self.transport is not None + + def connection_made(self, transport): + self.transport = transport + self.reader.set_transport(transport) + self.writer = StreamWriter(transport, self, self.reader, self._loop) + + def connection_lost(self, exc): + self.transport = self.writer = None + self.reader.set_transport(None) + + if exc is None: + self.reader.feed_eof() + else: + self.reader.set_exception(exc) + + super().connection_lost(exc) + + def data_received(self, data): + self.reader.feed_data(data) + + def eof_received(self): + self.reader.feed_eof() + + +class _ParserBufferHelper: + + __slots__ = ('exception', 'data') + + def __init__(self, exception, data): + self.exception = exception + self.data = data + + +class ParserBuffer: + """ParserBuffer is NOT a bytearray extension anymore. + + ParserBuffer provides helper methods for parsers. + """ + __slots__ = ('_helper', '_writer', '_data') + + def __init__(self, *args): + self._data = bytearray(*args) + self._helper = _ParserBufferHelper(None, self._data) + self._writer = self._feed_data(self._helper) + next(self._writer) + + def exception(self): + return self._helper.exception + + def set_exception(self, exc): + self._helper.exception = exc + + @staticmethod + def _feed_data(helper): + while True: + chunk = yield + if chunk: + helper.data.extend(chunk) + + if helper.exception: + raise helper.exception + + def feed_data(self, data): + if not self._helper.exception: + self._writer.send(data) + + def read(self, size): + """read() reads specified amount of bytes.""" + + while True: + if self._helper.exception: + raise self._helper.exception + + if len(self._data) >= size: + data = self._data[:size] + del self._data[:size] + return data + + self._writer.send((yield)) + + def readsome(self, size=None): + """reads size of less amount of bytes.""" + + while True: + if self._helper.exception: + raise self._helper.exception + + length = len(self._data) + if length > 0: + if size is None or length < size: + size = length + + data = self._data[:size] + del self._data[:size] + return data + + self._writer.send((yield)) + + def readuntil(self, stop, limit=None): + assert isinstance(stop, bytes) and stop, \ + 'bytes is required: {!r}'.format(stop) + + stop_len = len(stop) + + while True: + if self._helper.exception: + raise self._helper.exception + + pos = self._data.find(stop) + if pos >= 0: + end = pos + stop_len + size = end + if limit is not None and size > limit: + raise errors.LineLimitExceededParserError( + 'Line is too long.', limit) + + data = self._data[:size] + del self._data[:size] + return data + else: + if limit is not None and len(self._data) > limit: + raise errors.LineLimitExceededParserError( + 'Line is too long.', limit) + + self._writer.send((yield)) + + def wait(self, size): + """wait() waits for specified amount of bytes + then returns data without changing internal buffer.""" + + while True: + if self._helper.exception: + raise self._helper.exception + + if len(self._data) >= size: + return self._data[:size] + + self._writer.send((yield)) + + def waituntil(self, stop, limit=None): + """waituntil() reads until `stop` bytes sequence.""" + assert isinstance(stop, bytes) and stop, \ + 'bytes is required: {!r}'.format(stop) + + stop_len = len(stop) + + while True: + if self._helper.exception: + raise self._helper.exception + + pos = self._data.find(stop) + if pos >= 0: + size = pos + stop_len + if limit is not None and size > limit: + raise errors.LineLimitExceededParserError( + 'Line is too long. %s' % bytes(self._data), limit) + + return self._data[:size] + else: + if limit is not None and len(self._data) > limit: + raise errors.LineLimitExceededParserError( + 'Line is too long. %s' % bytes(self._data), limit) + + self._writer.send((yield)) + + def skip(self, size): + """skip() skips specified amount of bytes.""" + + while len(self._data) < size: + if self._helper.exception: + raise self._helper.exception + + self._writer.send((yield)) + + del self._data[:size] + + def skipuntil(self, stop): + """skipuntil() reads until `stop` bytes sequence.""" + assert isinstance(stop, bytes) and stop, \ + 'bytes is required: {!r}'.format(stop) + + stop_len = len(stop) + + while True: + if self._helper.exception: + raise self._helper.exception + + stop_line = self._data.find(stop) + if stop_line >= 0: + size = stop_line + stop_len + del self._data[:size] + return + + self._writer.send((yield)) + + def extend(self, data): + self._data.extend(data) + + def __len__(self): + return len(self._data) + + def __bytes__(self): + return bytes(self._data) diff --git a/venv/Lib/site-packages/aiohttp/payload.py b/venv/Lib/site-packages/aiohttp/payload.py deleted file mode 100644 index 7e633028..00000000 --- a/venv/Lib/site-packages/aiohttp/payload.py +++ /dev/null @@ -1,456 +0,0 @@ -import asyncio -import enum -import io -import json -import mimetypes -import os -import warnings -from abc import ABC, abstractmethod -from itertools import chain -from typing import ( - IO, - TYPE_CHECKING, - Any, - ByteString, - Dict, - Iterable, - Optional, - Text, - TextIO, - Tuple, - Type, - Union, -) - -from multidict import CIMultiDict - -from . import hdrs -from .abc import AbstractStreamWriter -from .helpers import ( - PY_36, - content_disposition_header, - guess_filename, - parse_mimetype, - sentinel, -) -from .streams import DEFAULT_LIMIT, StreamReader -from .typedefs import JSONEncoder, _CIMultiDict - -__all__ = ('PAYLOAD_REGISTRY', 'get_payload', 'payload_type', 'Payload', - 'BytesPayload', 'StringPayload', - 'IOBasePayload', 'BytesIOPayload', 'BufferedReaderPayload', - 'TextIOPayload', 'StringIOPayload', 'JsonPayload', - 'AsyncIterablePayload') - -TOO_LARGE_BYTES_BODY = 2 ** 20 # 1 MB - - -if TYPE_CHECKING: # pragma: no cover - from typing import List # noqa - - -class LookupError(Exception): - pass - - -class Order(str, enum.Enum): - normal = 'normal' - try_first = 'try_first' - try_last = 'try_last' - - -def get_payload(data: Any, *args: Any, **kwargs: Any) -> 'Payload': - return PAYLOAD_REGISTRY.get(data, *args, **kwargs) - - -def register_payload(factory: Type['Payload'], - type: Any, - *, - order: Order=Order.normal) -> None: - PAYLOAD_REGISTRY.register(factory, type, order=order) - - -class payload_type: - - def __init__(self, type: Any, *, order: Order=Order.normal) -> None: - self.type = type - self.order = order - - def __call__(self, factory: Type['Payload']) -> Type['Payload']: - register_payload(factory, self.type, order=self.order) - return factory - - -class PayloadRegistry: - """Payload registry. - - note: we need zope.interface for more efficient adapter search - """ - - def __init__(self) -> None: - self._first = [] # type: List[Tuple[Type[Payload], Any]] - self._normal = [] # type: List[Tuple[Type[Payload], Any]] - self._last = [] # type: List[Tuple[Type[Payload], Any]] - - def get(self, - data: Any, - *args: Any, - _CHAIN: Any=chain, - **kwargs: Any) -> 'Payload': - if isinstance(data, Payload): - return data - for factory, type in _CHAIN(self._first, self._normal, self._last): - if isinstance(data, type): - return factory(data, *args, **kwargs) - - raise LookupError() - - def register(self, - factory: Type['Payload'], - type: Any, - *, - order: Order=Order.normal) -> None: - if order is Order.try_first: - self._first.append((factory, type)) - elif order is Order.normal: - self._normal.append((factory, type)) - elif order is Order.try_last: - self._last.append((factory, type)) - else: - raise ValueError("Unsupported order {!r}".format(order)) - - -class Payload(ABC): - - _default_content_type = 'application/octet-stream' # type: str - _size = None # type: Optional[int] - - def __init__(self, - value: Any, - headers: Optional[ - Union[ - _CIMultiDict, - Dict[str, str], - Iterable[Tuple[str, str]] - ] - ] = None, - content_type: Optional[str]=sentinel, - filename: Optional[str]=None, - encoding: Optional[str]=None, - **kwargs: Any) -> None: - self._encoding = encoding - self._filename = filename - self._headers = CIMultiDict() # type: _CIMultiDict - self._value = value - if content_type is not sentinel and content_type is not None: - self._headers[hdrs.CONTENT_TYPE] = content_type - elif self._filename is not None: - content_type = mimetypes.guess_type(self._filename)[0] - if content_type is None: - content_type = self._default_content_type - self._headers[hdrs.CONTENT_TYPE] = content_type - else: - self._headers[hdrs.CONTENT_TYPE] = self._default_content_type - self._headers.update(headers or {}) - - @property - def size(self) -> Optional[int]: - """Size of the payload.""" - return self._size - - @property - def filename(self) -> Optional[str]: - """Filename of the payload.""" - return self._filename - - @property - def headers(self) -> _CIMultiDict: - """Custom item headers""" - return self._headers - - @property - def _binary_headers(self) -> bytes: - return ''.join( - [k + ': ' + v + '\r\n' for k, v in self.headers.items()] - ).encode('utf-8') + b'\r\n' - - @property - def encoding(self) -> Optional[str]: - """Payload encoding""" - return self._encoding - - @property - def content_type(self) -> str: - """Content type""" - return self._headers[hdrs.CONTENT_TYPE] - - def set_content_disposition(self, - disptype: str, - quote_fields: bool=True, - **params: Any) -> None: - """Sets ``Content-Disposition`` header.""" - self._headers[hdrs.CONTENT_DISPOSITION] = content_disposition_header( - disptype, quote_fields=quote_fields, **params) - - @abstractmethod - async def write(self, writer: AbstractStreamWriter) -> None: - """Write payload. - - writer is an AbstractStreamWriter instance: - """ - - -class BytesPayload(Payload): - - def __init__(self, - value: ByteString, - *args: Any, - **kwargs: Any) -> None: - if not isinstance(value, (bytes, bytearray, memoryview)): - raise TypeError("value argument must be byte-ish, not {!r}" - .format(type(value))) - - if 'content_type' not in kwargs: - kwargs['content_type'] = 'application/octet-stream' - - super().__init__(value, *args, **kwargs) - - self._size = len(value) - - if self._size > TOO_LARGE_BYTES_BODY: - if PY_36: - kwargs = {'source': self} - else: - kwargs = {} - warnings.warn("Sending a large body directly with raw bytes might" - " lock the event loop. You should probably pass an " - "io.BytesIO object instead", ResourceWarning, - **kwargs) - - async def write(self, writer: AbstractStreamWriter) -> None: - await writer.write(self._value) - - -class StringPayload(BytesPayload): - - def __init__(self, - value: Text, - *args: Any, - encoding: Optional[str]=None, - content_type: Optional[str]=None, - **kwargs: Any) -> None: - - if encoding is None: - if content_type is None: - real_encoding = 'utf-8' - content_type = 'text/plain; charset=utf-8' - else: - mimetype = parse_mimetype(content_type) - real_encoding = mimetype.parameters.get('charset', 'utf-8') - else: - if content_type is None: - content_type = 'text/plain; charset=%s' % encoding - real_encoding = encoding - - super().__init__( - value.encode(real_encoding), - encoding=real_encoding, - content_type=content_type, - *args, - **kwargs, - ) - - -class StringIOPayload(StringPayload): - - def __init__(self, - value: IO[str], - *args: Any, - **kwargs: Any) -> None: - super().__init__(value.read(), *args, **kwargs) - - -class IOBasePayload(Payload): - - def __init__(self, - value: IO[Any], - disposition: str='attachment', - *args: Any, - **kwargs: Any) -> None: - if 'filename' not in kwargs: - kwargs['filename'] = guess_filename(value) - - super().__init__(value, *args, **kwargs) - - if self._filename is not None and disposition is not None: - if hdrs.CONTENT_DISPOSITION not in self.headers: - self.set_content_disposition( - disposition, filename=self._filename - ) - - async def write(self, writer: AbstractStreamWriter) -> None: - loop = asyncio.get_event_loop() - try: - chunk = await loop.run_in_executor( - None, self._value.read, DEFAULT_LIMIT - ) - while chunk: - await writer.write(chunk) - chunk = await loop.run_in_executor( - None, self._value.read, DEFAULT_LIMIT - ) - finally: - await loop.run_in_executor(None, self._value.close) - - -class TextIOPayload(IOBasePayload): - - def __init__(self, - value: TextIO, - *args: Any, - encoding: Optional[str]=None, - content_type: Optional[str]=None, - **kwargs: Any) -> None: - - if encoding is None: - if content_type is None: - encoding = 'utf-8' - content_type = 'text/plain; charset=utf-8' - else: - mimetype = parse_mimetype(content_type) - encoding = mimetype.parameters.get('charset', 'utf-8') - else: - if content_type is None: - content_type = 'text/plain; charset=%s' % encoding - - super().__init__( - value, - content_type=content_type, - encoding=encoding, - *args, - **kwargs, - ) - - @property - def size(self) -> Optional[int]: - try: - return os.fstat(self._value.fileno()).st_size - self._value.tell() - except OSError: - return None - - async def write(self, writer: AbstractStreamWriter) -> None: - loop = asyncio.get_event_loop() - try: - chunk = await loop.run_in_executor( - None, self._value.read, DEFAULT_LIMIT - ) - while chunk: - await writer.write(chunk.encode(self._encoding)) - chunk = await loop.run_in_executor( - None, self._value.read, DEFAULT_LIMIT - ) - finally: - await loop.run_in_executor(None, self._value.close) - - -class BytesIOPayload(IOBasePayload): - - @property - def size(self) -> int: - position = self._value.tell() - end = self._value.seek(0, os.SEEK_END) - self._value.seek(position) - return end - position - - -class BufferedReaderPayload(IOBasePayload): - - @property - def size(self) -> Optional[int]: - try: - return os.fstat(self._value.fileno()).st_size - self._value.tell() - except OSError: - # data.fileno() is not supported, e.g. - # io.BufferedReader(io.BytesIO(b'data')) - return None - - -class JsonPayload(BytesPayload): - - def __init__(self, - value: Any, - encoding: str='utf-8', - content_type: str='application/json', - dumps: JSONEncoder=json.dumps, - *args: Any, - **kwargs: Any) -> None: - - super().__init__( - dumps(value).encode(encoding), - content_type=content_type, encoding=encoding, *args, **kwargs) - - -if TYPE_CHECKING: # pragma: no cover - from typing import AsyncIterator, AsyncIterable - - _AsyncIterator = AsyncIterator[bytes] - _AsyncIterable = AsyncIterable[bytes] -else: - from collections.abc import AsyncIterable, AsyncIterator - - _AsyncIterator = AsyncIterator - _AsyncIterable = AsyncIterable - - -class AsyncIterablePayload(Payload): - - _iter = None # type: Optional[_AsyncIterator] - - def __init__(self, - value: _AsyncIterable, - *args: Any, - **kwargs: Any) -> None: - if not isinstance(value, AsyncIterable): - raise TypeError("value argument must support " - "collections.abc.AsyncIterablebe interface, " - "got {!r}".format(type(value))) - - if 'content_type' not in kwargs: - kwargs['content_type'] = 'application/octet-stream' - - super().__init__(value, *args, **kwargs) - - self._iter = value.__aiter__() - - async def write(self, writer: AbstractStreamWriter) -> None: - if self._iter: - try: - # iter is not None check prevents rare cases - # when the case iterable is used twice - while True: - chunk = await self._iter.__anext__() - await writer.write(chunk) - except StopAsyncIteration: - self._iter = None - - -class StreamReaderPayload(AsyncIterablePayload): - - def __init__(self, value: StreamReader, *args: Any, **kwargs: Any) -> None: - super().__init__(value.iter_any(), *args, **kwargs) - - -PAYLOAD_REGISTRY = PayloadRegistry() -PAYLOAD_REGISTRY.register(BytesPayload, (bytes, bytearray, memoryview)) -PAYLOAD_REGISTRY.register(StringPayload, str) -PAYLOAD_REGISTRY.register(StringIOPayload, io.StringIO) -PAYLOAD_REGISTRY.register(TextIOPayload, io.TextIOBase) -PAYLOAD_REGISTRY.register(BytesIOPayload, io.BytesIO) -PAYLOAD_REGISTRY.register( - BufferedReaderPayload, (io.BufferedReader, io.BufferedRandom)) -PAYLOAD_REGISTRY.register(IOBasePayload, io.IOBase) -PAYLOAD_REGISTRY.register(StreamReaderPayload, StreamReader) -# try_last for giving a chance to more specialized async interables like -# multidict.BodyPartReaderPayload override the default -PAYLOAD_REGISTRY.register(AsyncIterablePayload, AsyncIterable, - order=Order.try_last) diff --git a/venv/Lib/site-packages/aiohttp/payload_streamer.py b/venv/Lib/site-packages/aiohttp/payload_streamer.py deleted file mode 100644 index e76bf430..00000000 --- a/venv/Lib/site-packages/aiohttp/payload_streamer.py +++ /dev/null @@ -1,74 +0,0 @@ -""" Payload implemenation for coroutines as data provider. - -As a simple case, you can upload data from file:: - - @aiohttp.streamer - async def file_sender(writer, file_name=None): - with open(file_name, 'rb') as f: - chunk = f.read(2**16) - while chunk: - await writer.write(chunk) - - chunk = f.read(2**16) - -Then you can use `file_sender` like this: - - async with session.post('http://httpbin.org/post', - data=file_sender(file_name='huge_file')) as resp: - print(await resp.text()) - -..note:: Coroutine must accept `writer` as first argument - -""" - -import asyncio -import warnings -from typing import Any, Awaitable, Callable, Dict, Tuple - -from .abc import AbstractStreamWriter -from .payload import Payload, payload_type - -__all__ = ('streamer',) - - -class _stream_wrapper: - - def __init__(self, - coro: Callable[..., Awaitable[None]], - args: Tuple[Any, ...], - kwargs: Dict[str, Any]) -> None: - self.coro = asyncio.coroutine(coro) - self.args = args - self.kwargs = kwargs - - async def __call__(self, writer: AbstractStreamWriter) -> None: - await self.coro(writer, *self.args, **self.kwargs) - - -class streamer: - - def __init__(self, coro: Callable[..., Awaitable[None]]) -> None: - warnings.warn("@streamer is deprecated, use async generators instead", - DeprecationWarning, - stacklevel=2) - self.coro = coro - - def __call__(self, *args: Any, **kwargs: Any) -> _stream_wrapper: - return _stream_wrapper(self.coro, args, kwargs) - - -@payload_type(_stream_wrapper) -class StreamWrapperPayload(Payload): - - async def write(self, writer: AbstractStreamWriter) -> None: - await self._value(writer) - - -@payload_type(streamer) -class StreamPayload(StreamWrapperPayload): - - def __init__(self, value: Any, *args: Any, **kwargs: Any) -> None: - super().__init__(value(), *args, **kwargs) - - async def write(self, writer: AbstractStreamWriter) -> None: - await self._value(writer) diff --git a/venv/Lib/site-packages/aiohttp/protocol.py b/venv/Lib/site-packages/aiohttp/protocol.py new file mode 100644 index 00000000..457f0cf5 --- /dev/null +++ b/venv/Lib/site-packages/aiohttp/protocol.py @@ -0,0 +1,916 @@ +"""Http related parsers and protocol.""" + +import collections +import functools +import http.server +import re +import string +import sys +import zlib +from abc import ABC, abstractmethod +from wsgiref.handlers import format_date_time + +from multidict import CIMultiDict, istr + +import aiohttp + +from . import errors, hdrs +from .helpers import reify +from .log import internal_logger + +__all__ = ('HttpMessage', 'Request', 'Response', + 'HttpVersion', 'HttpVersion10', 'HttpVersion11', + 'RawRequestMessage', 'RawResponseMessage', + 'HttpPrefixParser', 'HttpRequestParser', 'HttpResponseParser', + 'HttpPayloadParser') + +ASCIISET = set(string.printable) +METHRE = re.compile('[A-Z0-9$-_.]+') +VERSRE = re.compile('HTTP/(\d+).(\d+)') +HDRRE = re.compile(b'[\x00-\x1F\x7F()<>@,;:\[\]={} \t\\\\\"]') +EOF_MARKER = object() +EOL_MARKER = object() +STATUS_LINE_READY = object() + +RESPONSES = http.server.BaseHTTPRequestHandler.responses + +HttpVersion = collections.namedtuple( + 'HttpVersion', ['major', 'minor']) +HttpVersion10 = HttpVersion(1, 0) +HttpVersion11 = HttpVersion(1, 1) + +RawStatusLineMessage = collections.namedtuple( + 'RawStatusLineMessage', ['method', 'path', 'version']) + +RawRequestMessage = collections.namedtuple( + 'RawRequestMessage', + ['method', 'path', 'version', 'headers', 'raw_headers', + 'should_close', 'compression']) + + +RawResponseMessage = collections.namedtuple( + 'RawResponseMessage', + ['version', 'code', 'reason', 'headers', 'raw_headers', + 'should_close', 'compression']) + + +class HttpParser: + + def __init__(self, max_line_size=8190, max_headers=32768, + max_field_size=8190): + self.max_line_size = max_line_size + self.max_headers = max_headers + self.max_field_size = max_field_size + + def parse_headers(self, lines): + """Parses RFC 5322 headers from a stream. + + Line continuations are supported. Returns list of header name + and value pairs. Header name is in upper case. + """ + close_conn = None + encoding = None + headers = CIMultiDict() + raw_headers = [] + + lines_idx = 1 + line = lines[1] + + while line: + header_length = len(line) + + # Parse initial header name : value pair. + try: + bname, bvalue = line.split(b':', 1) + except ValueError: + raise errors.InvalidHeader(line) from None + + bname = bname.strip(b' \t').upper() + if HDRRE.search(bname): + raise errors.InvalidHeader(bname) + + # next line + lines_idx += 1 + line = lines[lines_idx] + + # consume continuation lines + continuation = line and line[0] in (32, 9) # (' ', '\t') + + if continuation: + bvalue = [bvalue] + while continuation: + header_length += len(line) + if header_length > self.max_field_size: + raise errors.LineTooLong( + 'limit request headers fields size') + bvalue.append(line) + + # next line + lines_idx += 1 + line = lines[lines_idx] + continuation = line[0] in (32, 9) # (' ', '\t') + bvalue = b'\r\n'.join(bvalue) + else: + if header_length > self.max_field_size: + raise errors.LineTooLong( + 'limit request headers fields size') + + bvalue = bvalue.strip() + + name = istr(bname.decode('utf-8', 'surrogateescape')) + value = bvalue.decode('utf-8', 'surrogateescape') + + # keep-alive and encoding + if name == hdrs.CONNECTION: + v = value.lower() + if v == 'close': + close_conn = True + elif v == 'keep-alive': + close_conn = False + elif name == hdrs.CONTENT_ENCODING: + enc = value.lower() + if enc in ('gzip', 'deflate'): + encoding = enc + + headers.add(name, value) + raw_headers.append((bname, bvalue)) + + return headers, raw_headers, close_conn, encoding + + +class HttpPrefixParser: + """Waits for 'HTTP' prefix (non destructive)""" + + def __init__(self, allowed_methods=()): + self.allowed_methods = [m.upper() for m in allowed_methods] + + def __call__(self, out, buf): + raw_data = yield from buf.waituntil(b' ', 12) + method = raw_data.decode('ascii', 'surrogateescape').strip() + + # method + method = method.upper() + if not METHRE.match(method): + raise errors.BadStatusLine(method) + + # allowed method + if self.allowed_methods and method not in self.allowed_methods: + raise errors.HttpMethodNotAllowed(message=method) + + out.feed_data(method, len(method)) + out.feed_eof() + + +class HttpRequestParser(HttpParser): + """Read request status line. Exception errors.BadStatusLine + could be raised in case of any errors in status line. + Returns RawRequestMessage. + """ + + def __call__(self, out, buf): + # read HTTP message (request line + headers) + try: + raw_data = yield from buf.readuntil( + b'\r\n\r\n', self.max_headers) + except errors.LineLimitExceededParserError as exc: + raise errors.LineTooLong(exc.limit) from None + + lines = raw_data.split(b'\r\n') + + # request line + line = lines[0].decode('utf-8', 'surrogateescape') + try: + method, path, version = line.split(None, 2) + except ValueError: + raise errors.BadStatusLine(line) from None + + # method + method = method.upper() + if not METHRE.match(method): + raise errors.BadStatusLine(method) + + # version + try: + if version.startswith('HTTP/'): + n1, n2 = version[5:].split('.', 1) + version = HttpVersion(int(n1), int(n2)) + else: + raise errors.BadStatusLine(version) + except: + raise errors.BadStatusLine(version) + + # read headers + headers, raw_headers, close, compression = self.parse_headers(lines) + if close is None: # then the headers weren't set in the request + if version <= HttpVersion10: # HTTP 1.0 must asks to not close + close = True + else: # HTTP 1.1 must ask to close. + close = False + + out.feed_data( + RawRequestMessage( + method, path, version, headers, raw_headers, + close, compression), + len(raw_data)) + out.feed_eof() + + +class HttpResponseParser(HttpParser): + """Read response status line and headers. + + BadStatusLine could be raised in case of any errors in status line. + Returns RawResponseMessage""" + + def __call__(self, out, buf): + # read HTTP message (response line + headers) + try: + raw_data = yield from buf.readuntil( + b'\r\n\r\n', self.max_line_size + self.max_headers) + except errors.LineLimitExceededParserError as exc: + raise errors.LineTooLong(exc.limit) from None + + lines = raw_data.split(b'\r\n') + + line = lines[0].decode('utf-8', 'surrogateescape') + try: + version, status = line.split(None, 1) + except ValueError: + raise errors.BadStatusLine(line) from None + else: + try: + status, reason = status.split(None, 1) + except ValueError: + reason = '' + + # version + match = VERSRE.match(version) + if match is None: + raise errors.BadStatusLine(line) + version = HttpVersion(int(match.group(1)), int(match.group(2))) + + # The status code is a three-digit number + try: + status = int(status) + except ValueError: + raise errors.BadStatusLine(line) from None + + if status < 100 or status > 999: + raise errors.BadStatusLine(line) + + # read headers + headers, raw_headers, close, compression = self.parse_headers(lines) + + if close is None: + close = version <= HttpVersion10 + + out.feed_data( + RawResponseMessage( + version, status, reason.strip(), + headers, raw_headers, close, compression), + len(raw_data)) + out.feed_eof() + + +class HttpPayloadParser: + + def __init__(self, message, length=None, compression=True, + readall=False, response_with_body=True): + self.message = message + self.length = length + self.compression = compression + self.readall = readall + self.response_with_body = response_with_body + + def __call__(self, out, buf): + # payload params + length = self.message.headers.get(hdrs.CONTENT_LENGTH, self.length) + if hdrs.SEC_WEBSOCKET_KEY1 in self.message.headers: + length = 8 + + # payload decompression wrapper + if (self.response_with_body and + self.compression and self.message.compression): + out = DeflateBuffer(out, self.message.compression) + + # payload parser + if not self.response_with_body: + # don't parse payload if it's not expected to be received + pass + + elif 'chunked' in self.message.headers.get( + hdrs.TRANSFER_ENCODING, ''): + yield from self.parse_chunked_payload(out, buf) + + elif length is not None: + try: + length = int(length) + except ValueError: + raise errors.InvalidHeader(hdrs.CONTENT_LENGTH) from None + + if length < 0: + raise errors.InvalidHeader(hdrs.CONTENT_LENGTH) + elif length > 0: + yield from self.parse_length_payload(out, buf, length) + else: + if self.readall and getattr(self.message, 'code', 0) != 204: + yield from self.parse_eof_payload(out, buf) + elif getattr(self.message, 'method', None) in ('PUT', 'POST'): + internal_logger.warning( # pragma: no cover + 'Content-Length or Transfer-Encoding header is required') + + out.feed_eof() + + def parse_chunked_payload(self, out, buf): + """Chunked transfer encoding parser.""" + while True: + # read next chunk size + line = yield from buf.readuntil(b'\r\n', 8192) + + i = line.find(b';') + if i >= 0: + line = line[:i] # strip chunk-extensions + else: + line = line.strip() + try: + size = int(line, 16) + except ValueError: + raise errors.TransferEncodingError(line) from None + + if size == 0: # eof marker + break + + # read chunk and feed buffer + while size: + chunk = yield from buf.readsome(size) + out.feed_data(chunk, len(chunk)) + size = size - len(chunk) + + # toss the CRLF at the end of the chunk + yield from buf.skip(2) + + # read and discard trailer up to the CRLF terminator + yield from buf.skipuntil(b'\r\n') + + def parse_length_payload(self, out, buf, length=0): + """Read specified amount of bytes.""" + required = length + while required: + chunk = yield from buf.readsome(required) + out.feed_data(chunk, len(chunk)) + required -= len(chunk) + + def parse_eof_payload(self, out, buf): + """Read all bytes until eof.""" + try: + while True: + chunk = yield from buf.readsome() + out.feed_data(chunk, len(chunk)) + except aiohttp.EofStream: + pass + + +class DeflateBuffer: + """DeflateStream decompress stream and feed data into specified stream.""" + + def __init__(self, out, encoding): + self.out = out + zlib_mode = (16 + zlib.MAX_WBITS + if encoding == 'gzip' else -zlib.MAX_WBITS) + + self.zlib = zlib.decompressobj(wbits=zlib_mode) + + def feed_data(self, chunk, size): + try: + chunk = self.zlib.decompress(chunk) + except Exception: + raise errors.ContentEncodingError('deflate') + + if chunk: + self.out.feed_data(chunk, len(chunk)) + + def feed_eof(self): + chunk = self.zlib.flush() + self.out.feed_data(chunk, len(chunk)) + if not self.zlib.eof: + raise errors.ContentEncodingError('deflate') + + self.out.feed_eof() + + +def wrap_payload_filter(func): + """Wraps payload filter and piped filters. + + Filter is a generator that accepts arbitrary chunks of data, + modify data and emit new stream of data. + + For example we have stream of chunks: ['1', '2', '3', '4', '5'], + we can apply chunking filter to this stream: + + ['1', '2', '3', '4', '5'] + | + response.add_chunking_filter(2) + | + ['12', '34', '5'] + + It is possible to use different filters at the same time. + + For a example to compress incoming stream with 'deflate' encoding + and then split data and emit chunks of 8192 bytes size chunks: + + >>> response.add_compression_filter('deflate') + >>> response.add_chunking_filter(8192) + + Filters do not alter transfer encoding. + + Filter can receive types types of data, bytes object or EOF_MARKER. + + 1. If filter receives bytes object, it should process data + and yield processed data then yield EOL_MARKER object. + 2. If Filter received EOF_MARKER, it should yield remaining + data (buffered) and then yield EOF_MARKER. + """ + @functools.wraps(func) + def wrapper(self, *args, **kw): + new_filter = func(self, *args, **kw) + + filter = self.filter + if filter is not None: + next(new_filter) + self.filter = filter_pipe(filter, new_filter) + else: + self.filter = new_filter + + next(self.filter) + + return wrapper + + +def filter_pipe(filter, filter2, *, + EOF_MARKER=EOF_MARKER, EOL_MARKER=EOL_MARKER): + """Creates pipe between two filters. + + filter_pipe() feeds first filter with incoming data and then + send yielded from first filter data into filter2, results of + filter2 are being emitted. + + 1. If filter_pipe receives bytes object, it sends it to the first filter. + 2. Reads yielded values from the first filter until it receives + EOF_MARKER or EOL_MARKER. + 3. Each of this values is being send to second filter. + 4. Reads yielded values from second filter until it receives EOF_MARKER + or EOL_MARKER. Each of this values yields to writer. + """ + chunk = yield + + while True: + eof = chunk is EOF_MARKER + chunk = filter.send(chunk) + + while chunk is not EOL_MARKER: + chunk = filter2.send(chunk) + + while chunk not in (EOF_MARKER, EOL_MARKER): + yield chunk + chunk = next(filter2) + + if chunk is not EOF_MARKER: + if eof: + chunk = EOF_MARKER + else: + chunk = next(filter) + else: + break + + chunk = yield EOL_MARKER + + +class HttpMessage(ABC): + """HttpMessage allows to write headers and payload to a stream. + + For example, lets say we want to read file then compress it with deflate + compression and then send it with chunked transfer encoding, code may look + like this: + + >>> response = aiohttp.Response(transport, 200) + + We have to use deflate compression first: + + >>> response.add_compression_filter('deflate') + + Then we want to split output stream into chunks of 1024 bytes size: + + >>> response.add_chunking_filter(1024) + + We can add headers to response with add_headers() method. add_headers() + does not send data to transport, send_headers() sends request/response + line and then sends headers: + + >>> response.add_headers( + ... ('Content-Disposition', 'attachment; filename="..."')) + >>> response.send_headers() + + Now we can use chunked writer to write stream to a network stream. + First call to write() method sends response status line and headers, + add_header() and add_headers() method unavailable at this stage: + + >>> with open('...', 'rb') as f: + ... chunk = fp.read(8192) + ... while chunk: + ... response.write(chunk) + ... chunk = fp.read(8192) + + >>> response.write_eof() + + """ + + writer = None + + # 'filter' is being used for altering write() behaviour, + # add_chunking_filter adds deflate/gzip compression and + # add_compression_filter splits incoming data into a chunks. + filter = None + + HOP_HEADERS = None # Must be set by subclass. + + SERVER_SOFTWARE = 'Python/{0[0]}.{0[1]} aiohttp/{1}'.format( + sys.version_info, aiohttp.__version__) + + upgrade = False # Connection: UPGRADE + websocket = False # Upgrade: WEBSOCKET + has_chunked_hdr = False # Transfer-encoding: chunked + + # subclass can enable auto sending headers with write() call, + # this is useful for wsgi's start_response implementation. + _send_headers = False + + def __init__(self, transport, version, close): + self.transport = transport + self._version = version + self.closing = close + self.keepalive = None + self.chunked = False + self.length = None + self.headers = CIMultiDict() + self.headers_sent = False + self.output_length = 0 + self.headers_length = 0 + self._output_size = 0 + + @property + @abstractmethod + def status_line(self): + return b'' + + @abstractmethod + def autochunked(self): + return False + + @property + def version(self): + return self._version + + @property + def body_length(self): + return self.output_length - self.headers_length + + def force_close(self): + self.closing = True + self.keepalive = False + + def enable_chunked_encoding(self): + self.chunked = True + + def keep_alive(self): + if self.keepalive is None: + if self.version < HttpVersion10: + # keep alive not supported at all + return False + if self.version == HttpVersion10: + if self.headers.get(hdrs.CONNECTION) == 'keep-alive': + return True + else: # no headers means we close for Http 1.0 + return False + else: + return not self.closing + else: + return self.keepalive + + def is_headers_sent(self): + return self.headers_sent + + def add_header(self, name, value): + """Analyze headers. Calculate content length, + removes hop headers, etc.""" + assert not self.headers_sent, 'headers have been sent already' + assert isinstance(name, str), \ + 'Header name should be a string, got {!r}'.format(name) + assert set(name).issubset(ASCIISET), \ + 'Header name should contain ASCII chars, got {!r}'.format(name) + assert isinstance(value, str), \ + 'Header {!r} should have string value, got {!r}'.format( + name, value) + + name = istr(name) + value = value.strip() + + if name == hdrs.CONTENT_LENGTH: + self.length = int(value) + + if name == hdrs.TRANSFER_ENCODING: + self.has_chunked_hdr = value.lower().strip() == 'chunked' + + if name == hdrs.CONNECTION: + val = value.lower() + # handle websocket + if 'upgrade' in val: + self.upgrade = True + # connection keep-alive + elif 'close' in val: + self.keepalive = False + elif 'keep-alive' in val: + self.keepalive = True + + elif name == hdrs.UPGRADE: + if 'websocket' in value.lower(): + self.websocket = True + self.headers[name] = value + + elif name not in self.HOP_HEADERS: + # ignore hop-by-hop headers + self.headers.add(name, value) + + def add_headers(self, *headers): + """Adds headers to a HTTP message.""" + for name, value in headers: + self.add_header(name, value) + + def send_headers(self, _sep=': ', _end='\r\n'): + """Writes headers to a stream. Constructs payload writer.""" + # Chunked response is only for HTTP/1.1 clients or newer + # and there is no Content-Length header is set. + # Do not use chunked responses when the response is guaranteed to + # not have a response body (304, 204). + assert not self.headers_sent, 'headers have been sent already' + self.headers_sent = True + + if self.chunked or self.autochunked(): + self.writer = self._write_chunked_payload() + self.headers[hdrs.TRANSFER_ENCODING] = 'chunked' + + elif self.length is not None: + self.writer = self._write_length_payload(self.length) + + else: + self.writer = self._write_eof_payload() + + next(self.writer) + + self._add_default_headers() + + # status + headers + headers = self.status_line + ''.join( + [k + _sep + v + _end for k, v in self.headers.items()]) + headers = headers.encode('utf-8') + b'\r\n' + + self.output_length += len(headers) + self.headers_length = len(headers) + self.transport.write(headers) + + def _add_default_headers(self): + # set the connection header + connection = None + if self.upgrade: + connection = 'upgrade' + elif not self.closing if self.keepalive is None else self.keepalive: + if self.version == HttpVersion10: + connection = 'keep-alive' + else: + if self.version == HttpVersion11: + connection = 'close' + + if connection is not None: + self.headers[hdrs.CONNECTION] = connection + + def write(self, chunk, *, + drain=False, EOF_MARKER=EOF_MARKER, EOL_MARKER=EOL_MARKER): + """Writes chunk of data to a stream by using different writers. + + writer uses filter to modify chunk of data. + write_eof() indicates end of stream. + writer can't be used after write_eof() method being called. + write() return drain future. + """ + assert (isinstance(chunk, (bytes, bytearray)) or + chunk is EOF_MARKER), chunk + + size = self.output_length + + if self._send_headers and not self.headers_sent: + self.send_headers() + + assert self.writer is not None, 'send_headers() is not called.' + + if self.filter: + chunk = self.filter.send(chunk) + while chunk not in (EOF_MARKER, EOL_MARKER): + if chunk: + self.writer.send(chunk) + chunk = next(self.filter) + else: + if chunk is not EOF_MARKER: + self.writer.send(chunk) + + self._output_size += self.output_length - size + + if self._output_size > 64 * 1024: + if drain: + self._output_size = 0 + return self.transport.drain() + + return () + + def write_eof(self): + self.write(EOF_MARKER) + try: + self.writer.throw(aiohttp.EofStream()) + except StopIteration: + pass + + return self.transport.drain() + + def _write_chunked_payload(self): + """Write data in chunked transfer encoding.""" + while True: + try: + chunk = yield + except aiohttp.EofStream: + self.transport.write(b'0\r\n\r\n') + self.output_length += 5 + break + + chunk = bytes(chunk) + chunk_len = '{:x}\r\n'.format(len(chunk)).encode('ascii') + self.transport.write(chunk_len + chunk + b'\r\n') + self.output_length += len(chunk_len) + len(chunk) + 2 + + def _write_length_payload(self, length): + """Write specified number of bytes to a stream.""" + while True: + try: + chunk = yield + except aiohttp.EofStream: + break + + if length: + l = len(chunk) + if length >= l: + self.transport.write(chunk) + self.output_length += l + length = length-l + else: + self.transport.write(chunk[:length]) + self.output_length += length + length = 0 + + def _write_eof_payload(self): + while True: + try: + chunk = yield + except aiohttp.EofStream: + break + + self.transport.write(chunk) + self.output_length += len(chunk) + + @wrap_payload_filter + def add_chunking_filter(self, chunk_size=16*1024, *, + EOF_MARKER=EOF_MARKER, EOL_MARKER=EOL_MARKER): + """Split incoming stream into chunks.""" + buf = bytearray() + chunk = yield + + while True: + if chunk is EOF_MARKER: + if buf: + yield buf + + yield EOF_MARKER + + else: + buf.extend(chunk) + + while len(buf) >= chunk_size: + chunk = bytes(buf[:chunk_size]) + del buf[:chunk_size] + yield chunk + + chunk = yield EOL_MARKER + + @wrap_payload_filter + def add_compression_filter(self, encoding='deflate', *, + EOF_MARKER=EOF_MARKER, EOL_MARKER=EOL_MARKER): + """Compress incoming stream with deflate or gzip encoding.""" + zlib_mode = (16 + zlib.MAX_WBITS + if encoding == 'gzip' else -zlib.MAX_WBITS) + zcomp = zlib.compressobj(wbits=zlib_mode) + + chunk = yield + while True: + if chunk is EOF_MARKER: + yield zcomp.flush() + chunk = yield EOF_MARKER + + else: + yield zcomp.compress(chunk) + chunk = yield EOL_MARKER + + +class Response(HttpMessage): + """Create HTTP response message. + + Transport is a socket stream transport. status is a response status code, + status has to be integer value. http_version is a tuple that represents + HTTP version, (1, 0) stands for HTTP/1.0 and (1, 1) is for HTTP/1.1 + """ + + HOP_HEADERS = () + + @staticmethod + def calc_reason(status, *, _RESPONSES=RESPONSES): + record = _RESPONSES.get(status) + if record is not None: + reason = record[0] + else: + reason = str(status) + return reason + + def __init__(self, transport, status, + http_version=HttpVersion11, close=False, reason=None): + super().__init__(transport, http_version, close) + + self._status = status + if reason is None: + reason = self.calc_reason(status) + + self._reason = reason + + @property + def status(self): + return self._status + + @property + def reason(self): + return self._reason + + @reify + def status_line(self): + version = self.version + return 'HTTP/{}.{} {} {}\r\n'.format( + version[0], version[1], self.status, self.reason) + + def autochunked(self): + return (self.length is None and + self.version >= HttpVersion11) + + def _add_default_headers(self): + super()._add_default_headers() + + if hdrs.DATE not in self.headers: + # format_date_time(None) is quite expensive + self.headers.setdefault(hdrs.DATE, format_date_time(None)) + self.headers.setdefault(hdrs.SERVER, self.SERVER_SOFTWARE) + + +class Request(HttpMessage): + + HOP_HEADERS = () + + def __init__(self, transport, method, path, + http_version=HttpVersion11, close=False): + # set the default for HTTP 0.9 to be different + # will only be overwritten with keep-alive header + if http_version < HttpVersion10: + close = True + + super().__init__(transport, http_version, close) + + self._method = method + self._path = path + + @property + def method(self): + return self._method + + @property + def path(self): + return self._path + + @reify + def status_line(self): + return '{0} {1} HTTP/{2[0]}.{2[1]}\r\n'.format( + self.method, self.path, self.version) + + def autochunked(self): + return (self.length is None and + self.version >= HttpVersion11 and + self.status not in (304, 204)) diff --git a/venv/Lib/site-packages/aiohttp/py.typed b/venv/Lib/site-packages/aiohttp/py.typed deleted file mode 100644 index 20a74394..00000000 --- a/venv/Lib/site-packages/aiohttp/py.typed +++ /dev/null @@ -1 +0,0 @@ -Marker \ No newline at end of file diff --git a/venv/Lib/site-packages/aiohttp/pytest_plugin.py b/venv/Lib/site-packages/aiohttp/pytest_plugin.py index c01ca6c6..f22b819f 100644 --- a/venv/Lib/site-packages/aiohttp/pytest_plugin.py +++ b/venv/Lib/site-packages/aiohttp/pytest_plugin.py @@ -1,142 +1,17 @@ import asyncio import contextlib -import warnings -from collections.abc import Callable import pytest -from aiohttp.helpers import PY_37, isasyncgenfunction from aiohttp.web import Application -from .test_utils import ( - BaseTestServer, - RawTestServer, - TestClient, - TestServer, - loop_context, - setup_test_loop, - teardown_test_loop, -) from .test_utils import unused_port as _unused_port - -try: - import uvloop -except ImportError: # pragma: no cover - uvloop = None - -try: - import tokio -except ImportError: # pragma: no cover - tokio = None - - -def pytest_addoption(parser): # type: ignore - parser.addoption( - '--aiohttp-fast', action='store_true', default=False, - help='run tests faster by disabling extra checks') - parser.addoption( - '--aiohttp-loop', action='store', default='pyloop', - help='run tests with specific loop: pyloop, uvloop, tokio or all') - parser.addoption( - '--aiohttp-enable-loop-debug', action='store_true', default=False, - help='enable event loop debug mode') - - -def pytest_fixture_setup(fixturedef): # type: ignore - """ - Allow fixtures to be coroutines. Run coroutine fixtures in an event loop. - """ - func = fixturedef.func - - if isasyncgenfunction(func): - # async generator fixture - is_async_gen = True - elif asyncio.iscoroutinefunction(func): - # regular async fixture - is_async_gen = False - else: - # not an async fixture, nothing to do - return - - strip_request = False - if 'request' not in fixturedef.argnames: - fixturedef.argnames += ('request',) - strip_request = True - - def wrapper(*args, **kwargs): # type: ignore - request = kwargs['request'] - if strip_request: - del kwargs['request'] - - # if neither the fixture nor the test use the 'loop' fixture, - # 'getfixturevalue' will fail because the test is not parameterized - # (this can be removed someday if 'loop' is no longer parameterized) - if 'loop' not in request.fixturenames: - raise Exception( - "Asynchronous fixtures must depend on the 'loop' fixture or " - "be used in tests depending from it." - ) - - _loop = request.getfixturevalue('loop') - - if is_async_gen: - # for async generators, we need to advance the generator once, - # then advance it again in a finalizer - gen = func(*args, **kwargs) - - def finalizer(): # type: ignore - try: - return _loop.run_until_complete(gen.__anext__()) - except StopAsyncIteration: # NOQA - pass - - request.addfinalizer(finalizer) - return _loop.run_until_complete(gen.__anext__()) - else: - return _loop.run_until_complete(func(*args, **kwargs)) - - fixturedef.func = wrapper - - -@pytest.fixture -def fast(request): # type: ignore - """--fast config option""" - return request.config.getoption('--aiohttp-fast') - - -@pytest.fixture -def loop_debug(request): # type: ignore - """--enable-loop-debug config option""" - return request.config.getoption('--aiohttp-enable-loop-debug') +from .test_utils import (TestClient, TestServer, loop_context, setup_test_loop, + teardown_test_loop) @contextlib.contextmanager -def _runtime_warning_context(): # type: ignore - """ - Context manager which checks for RuntimeWarnings, specifically to - avoid "coroutine 'X' was never awaited" warnings being missed. - - If RuntimeWarnings occur in the context a RuntimeError is raised. - """ - with warnings.catch_warnings(record=True) as _warnings: - yield - rw = ['{w.filename}:{w.lineno}:{w.message}'.format(w=w) - for w in _warnings # type: ignore - if w.category == RuntimeWarning] - if rw: - raise RuntimeError('{} Runtime Warning{},\n{}'.format( - len(rw), - '' if len(rw) == 1 else 's', - '\n'.join(rw) - )) - - -@contextlib.contextmanager -def _passthrough_loop_context(loop, fast=False): # type: ignore - """ - setups and tears down a loop unless one is passed in via the loop - argument when it's passed straight through. - """ +def _passthrough_loop_context(loop): if loop: # loop already exists, pass it straight through yield loop @@ -144,10 +19,10 @@ def _passthrough_loop_context(loop, fast=False): # type: ignore # this shadows loop_context's standard behavior loop = setup_test_loop() yield loop - teardown_test_loop(loop, fast=fast) + teardown_test_loop(loop) -def pytest_pycollect_makeitem(collector, name, obj): # type: ignore +def pytest_pycollect_makeitem(collector, name, obj): """ Fix pytest collecting for coroutines. """ @@ -155,198 +30,84 @@ def pytest_pycollect_makeitem(collector, name, obj): # type: ignore return list(collector._genfunctions(name, obj)) -def pytest_pyfunc_call(pyfuncitem): # type: ignore +def pytest_pyfunc_call(pyfuncitem): """ Run coroutines in an event loop instead of a normal function call. """ - fast = pyfuncitem.config.getoption("--aiohttp-fast") if asyncio.iscoroutinefunction(pyfuncitem.function): - existing_loop = pyfuncitem.funcargs.get('proactor_loop')\ - or pyfuncitem.funcargs.get('loop', None) - with _runtime_warning_context(): - with _passthrough_loop_context(existing_loop, fast=fast) as _loop: - testargs = {arg: pyfuncitem.funcargs[arg] - for arg in pyfuncitem._fixtureinfo.argnames} - _loop.run_until_complete(pyfuncitem.obj(**testargs)) + existing_loop = pyfuncitem.funcargs.get('loop', None) + with _passthrough_loop_context(existing_loop) as _loop: + testargs = {arg: pyfuncitem.funcargs[arg] + for arg in pyfuncitem._fixtureinfo.argnames} - return True - - -def pytest_generate_tests(metafunc): # type: ignore - if 'loop_factory' not in metafunc.fixturenames: - return - - loops = metafunc.config.option.aiohttp_loop - avail_factories = {'pyloop': asyncio.DefaultEventLoopPolicy} - - if uvloop is not None: # pragma: no cover - avail_factories['uvloop'] = uvloop.EventLoopPolicy - - if tokio is not None: # pragma: no cover - avail_factories['tokio'] = tokio.EventLoopPolicy - - if loops == 'all': - loops = 'pyloop,uvloop?,tokio?' - - factories = {} # type: ignore - for name in loops.split(','): - required = not name.endswith('?') - name = name.strip(' ?') - if name not in avail_factories: # pragma: no cover - if required: - raise ValueError( - "Unknown loop '%s', available loops: %s" % ( - name, list(factories.keys()))) - else: - continue - factories[name] = avail_factories[name] - metafunc.parametrize("loop_factory", - list(factories.values()), - ids=list(factories.keys())) - - -@pytest.fixture -def loop(loop_factory, fast, loop_debug): # type: ignore - """Return an instance of the event loop.""" - policy = loop_factory() - asyncio.set_event_loop_policy(policy) - with loop_context(fast=fast) as _loop: - if loop_debug: - _loop.set_debug(True) # pragma: no cover - asyncio.set_event_loop(_loop) - yield _loop + task = _loop.create_task(pyfuncitem.obj(**testargs)) + _loop.run_until_complete(task) + return True -@pytest.fixture -def proactor_loop(): # type: ignore - if not PY_37: - policy = asyncio.get_event_loop_policy() - policy._loop_factory = asyncio.ProactorEventLoop # type: ignore - else: - policy = asyncio.WindowsProactorEventLoopPolicy() # type: ignore - asyncio.set_event_loop_policy(policy) - with loop_context(policy.new_event_loop) as _loop: - asyncio.set_event_loop(_loop) +@pytest.yield_fixture +def loop(): + with loop_context() as _loop: yield _loop @pytest.fixture -def unused_port(aiohttp_unused_port): # type: ignore # pragma: no cover - warnings.warn("Deprecated, use aiohttp_unused_port fixture instead", - DeprecationWarning) - return aiohttp_unused_port - - -@pytest.fixture -def aiohttp_unused_port(): # type: ignore - """Return a port that is unused on the current host.""" +def unused_port(): return _unused_port -@pytest.fixture -def aiohttp_server(loop): # type: ignore - """Factory to create a TestServer instance, given an app. - - aiohttp_server(app, **kwargs) - """ +@pytest.yield_fixture +def test_server(loop): servers = [] - async def go(app, *, port=None, **kwargs): # type: ignore - server = TestServer(app, port=port) - await server.start_server(loop=loop, **kwargs) - servers.append(server) - return server - - yield go - - async def finalize(): # type: ignore - while servers: - await servers.pop().close() - - loop.run_until_complete(finalize()) - - -@pytest.fixture -def test_server(aiohttp_server): # type: ignore # pragma: no cover - warnings.warn("Deprecated, use aiohttp_server fixture instead", - DeprecationWarning) - return aiohttp_server - + @asyncio.coroutine + def go(app, **kwargs): + assert app.loop is loop, \ + "Application is attached to other event loop" -@pytest.fixture -def aiohttp_raw_server(loop): # type: ignore - """Factory to create a RawTestServer instance, given a web handler. - - aiohttp_raw_server(handler, **kwargs) - """ - servers = [] - - async def go(handler, *, port=None, **kwargs): # type: ignore - server = RawTestServer(handler, port=port) - await server.start_server(loop=loop, **kwargs) + server = TestServer(app) + yield from server.start_server(**kwargs) servers.append(server) return server yield go - async def finalize(): # type: ignore + @asyncio.coroutine + def finalize(): while servers: - await servers.pop().close() + yield from servers.pop().close() loop.run_until_complete(finalize()) -@pytest.fixture -def raw_test_server(aiohttp_raw_server): # type: ignore # pragma: no cover - warnings.warn("Deprecated, use aiohttp_raw_server fixture instead", - DeprecationWarning) - return aiohttp_raw_server - - -@pytest.fixture -def aiohttp_client(loop): # type: ignore - """Factory to create a TestClient instance. - - aiohttp_client(app, **kwargs) - aiohttp_client(server, **kwargs) - aiohttp_client(raw_server, **kwargs) - """ +@pytest.yield_fixture +def test_client(loop): clients = [] - async def go(__param, *args, server_kwargs=None, **kwargs): # type: ignore - - if (isinstance(__param, Callable) and # type: ignore - not isinstance(__param, (Application, BaseTestServer))): - __param = __param(loop, *args, **kwargs) - kwargs = {} - else: - assert not args, "args should be empty" - + @asyncio.coroutine + def go(__param, *args, **kwargs): if isinstance(__param, Application): - server_kwargs = server_kwargs or {} - server = TestServer(__param, loop=loop, **server_kwargs) - client = TestClient(server, loop=loop, **kwargs) - elif isinstance(__param, BaseTestServer): - client = TestClient(__param, loop=loop, **kwargs) + assert not args, "args should be empty" + assert not kwargs, "kwargs should be empty" + assert __param.loop is loop, \ + "Application is attached to other event loop" + elif isinstance(__param, TestServer): + assert __param.app.loop is loop, \ + "TestServer is attached to other event loop" else: - raise ValueError("Unknown argument type: %r" % type(__param)) + __param = __param(loop, *args, **kwargs) - await client.start_server() + client = TestClient(__param) + yield from client.start_server() clients.append(client) return client yield go - async def finalize(): # type: ignore + @asyncio.coroutine + def finalize(): while clients: - await clients.pop().close() + yield from clients.pop().close() loop.run_until_complete(finalize()) - - -@pytest.fixture -def test_client(aiohttp_client): # type: ignore # pragma: no cover - warnings.warn("Deprecated, use aiohttp_client fixture instead", - DeprecationWarning) - return aiohttp_client diff --git a/venv/Lib/site-packages/aiohttp/resolver.py b/venv/Lib/site-packages/aiohttp/resolver.py index e0b6e130..e66e412a 100644 --- a/venv/Lib/site-packages/aiohttp/resolver.py +++ b/venv/Lib/site-packages/aiohttp/resolver.py @@ -1,19 +1,16 @@ import asyncio import socket -from typing import Any, Dict, List, Optional from .abc import AbstractResolver -from .helpers import get_running_loop __all__ = ('ThreadedResolver', 'AsyncResolver', 'DefaultResolver') try: import aiodns - # aiodns_default = hasattr(aiodns.DNSResolver, 'gethostbyname') + aiodns_default = hasattr(aiodns.DNSResolver, 'gethostbyname') except ImportError: # pragma: no cover aiodns = None - -aiodns_default = False + aiodns_default = False class ThreadedResolver(AbstractResolver): @@ -21,12 +18,14 @@ class ThreadedResolver(AbstractResolver): concurrent.futures.ThreadPoolExecutor. """ - def __init__(self, loop: Optional[asyncio.AbstractEventLoop]=None) -> None: - self._loop = get_running_loop(loop) + def __init__(self, loop=None): + if loop is None: + loop = asyncio.get_event_loop() + self._loop = loop - async def resolve(self, host: str, port: int=0, - family: int=socket.AF_INET) -> List[Dict[str, Any]]: - infos = await self._loop.getaddrinfo( + @asyncio.coroutine + def resolve(self, host, port=0, family=socket.AF_INET): + infos = yield from self._loop.getaddrinfo( host, port, type=socket.SOCK_STREAM, family=family) hosts = [] @@ -39,60 +38,51 @@ class ThreadedResolver(AbstractResolver): return hosts - async def close(self) -> None: + @asyncio.coroutine + def close(self): pass class AsyncResolver(AbstractResolver): """Use the `aiodns` package to make asynchronous DNS lookups""" - def __init__(self, loop: Optional[asyncio.AbstractEventLoop]=None, - *args: Any, **kwargs: Any) -> None: + def __init__(self, loop=None, *args, **kwargs): + if loop is None: + loop = asyncio.get_event_loop() + if aiodns is None: raise RuntimeError("Resolver requires aiodns library") - self._loop = get_running_loop(loop) + self._loop = loop self._resolver = aiodns.DNSResolver(*args, loop=loop, **kwargs) if not hasattr(self._resolver, 'gethostbyname'): # aiodns 1.1 is not available, fallback to DNSResolver.query - self.resolve = self._resolve_with_query # type: ignore - - async def resolve(self, host: str, port: int=0, - family: int=socket.AF_INET) -> List[Dict[str, Any]]: - try: - resp = await self._resolver.gethostbyname(host, family) - except aiodns.error.DNSError as exc: - msg = exc.args[1] if len(exc.args) >= 1 else "DNS lookup failed" - raise OSError(msg) from exc + self.resolve = self.resolve_with_query + + @asyncio.coroutine + def resolve(self, host, port=0, family=socket.AF_INET): hosts = [] + resp = yield from self._resolver.gethostbyname(host, family) + for address in resp.addresses: hosts.append( {'hostname': host, 'host': address, 'port': port, 'family': family, 'proto': 0, 'flags': socket.AI_NUMERICHOST}) - - if not hosts: - raise OSError("DNS lookup failed") - return hosts - async def _resolve_with_query( - self, host: str, port: int=0, - family: int=socket.AF_INET) -> List[Dict[str, Any]]: + @asyncio.coroutine + def resolve_with_query(self, host, port=0, family=socket.AF_INET): if family == socket.AF_INET6: qtype = 'AAAA' else: qtype = 'A' - try: - resp = await self._resolver.query(host, qtype) - except aiodns.error.DNSError as exc: - msg = exc.args[1] if len(exc.args) >= 1 else "DNS lookup failed" - raise OSError(msg) from exc - hosts = [] + resp = yield from self._resolver.query(host, qtype) + for rr in resp: hosts.append( {'hostname': host, @@ -100,12 +90,10 @@ class AsyncResolver(AbstractResolver): 'family': family, 'proto': 0, 'flags': socket.AI_NUMERICHOST}) - if not hosts: - raise OSError("DNS lookup failed") - return hosts - async def close(self) -> None: + @asyncio.coroutine + def close(self): return self._resolver.cancel() diff --git a/venv/Lib/site-packages/aiohttp/server.py b/venv/Lib/site-packages/aiohttp/server.py new file mode 100644 index 00000000..9223a1f9 --- /dev/null +++ b/venv/Lib/site-packages/aiohttp/server.py @@ -0,0 +1,376 @@ +"""simple HTTP server.""" + +import asyncio +import http.server +import socket +import traceback +import warnings +from contextlib import suppress +from html import escape as html_escape + +import aiohttp +from aiohttp import errors, hdrs, helpers, streams +from aiohttp.helpers import Timeout, _get_kwarg, ensure_future +from aiohttp.log import access_logger, server_logger + +__all__ = ('ServerHttpProtocol',) + + +RESPONSES = http.server.BaseHTTPRequestHandler.responses +DEFAULT_ERROR_MESSAGE = """ + + + {status} {reason} + + +

{status} {reason}

+ {message} + +""" + + +if hasattr(socket, 'SO_KEEPALIVE'): + def tcp_keepalive(server, transport): + sock = transport.get_extra_info('socket') + sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) +else: + def tcp_keepalive(server, transport): # pragma: no cover + pass + +EMPTY_PAYLOAD = streams.EmptyStreamReader() + + +class ServerHttpProtocol(aiohttp.StreamProtocol): + """Simple HTTP protocol implementation. + + ServerHttpProtocol handles incoming HTTP request. It reads request line, + request headers and request payload and calls handle_request() method. + By default it always returns with 404 response. + + ServerHttpProtocol handles errors in incoming request, like bad + status line, bad headers or incomplete payload. If any error occurs, + connection gets closed. + + :param keepalive_timeout: number of seconds before closing + keep-alive connection + :type keepalive_timeout: int or None + + :param bool tcp_keepalive: TCP keep-alive is on, default is on + + :param int slow_request_timeout: slow request timeout + + :param bool debug: enable debug mode + + :param logger: custom logger object + :type logger: aiohttp.log.server_logger + + :param access_log: custom logging object + :type access_log: aiohttp.log.server_logger + + :param str access_log_format: access log format string + + :param loop: Optional event loop + + :param int max_line_size: Optional maximum header line size + + :param int max_field_size: Optional maximum header field size + + :param int max_headers: Optional maximum header size + + """ + _request_count = 0 + _request_handler = None + _reading_request = False + _keepalive = False # keep transport open + + def __init__(self, *, loop=None, + keepalive_timeout=75, # NGINX default value is 75 secs + tcp_keepalive=True, + slow_request_timeout=0, + logger=server_logger, + access_log=access_logger, + access_log_format=helpers.AccessLogger.LOG_FORMAT, + debug=False, + max_line_size=8190, + max_headers=32768, + max_field_size=8190, + **kwargs): + + # process deprecated params + logger = _get_kwarg(kwargs, 'log', 'logger', logger) + + tcp_keepalive = _get_kwarg(kwargs, 'keep_alive_on', + 'tcp_keepalive', tcp_keepalive) + + keepalive_timeout = _get_kwarg(kwargs, 'keep_alive', + 'keepalive_timeout', keepalive_timeout) + + slow_request_timeout = _get_kwarg(kwargs, 'timeout', + 'slow_request_timeout', + slow_request_timeout) + + super().__init__( + loop=loop, + disconnect_error=errors.ClientDisconnectedError, **kwargs) + + self._tcp_keepalive = tcp_keepalive + self._keepalive_timeout = keepalive_timeout + self._slow_request_timeout = slow_request_timeout + self._loop = loop if loop is not None else asyncio.get_event_loop() + + self._request_prefix = aiohttp.HttpPrefixParser() + self._request_parser = aiohttp.HttpRequestParser( + max_line_size=max_line_size, + max_field_size=max_field_size, + max_headers=max_headers) + + self.logger = logger + self.debug = debug + self.access_log = access_log + if access_log: + self.access_logger = helpers.AccessLogger(access_log, + access_log_format) + else: + self.access_logger = None + self._closing = False + + @property + def keep_alive_timeout(self): + warnings.warn("Use keepalive_timeout property instead", + DeprecationWarning, + stacklevel=2) + return self._keepalive_timeout + + @property + def keepalive_timeout(self): + return self._keepalive_timeout + + @asyncio.coroutine + def shutdown(self, timeout=15.0): + """Worker process is about to exit, we need cleanup everything and + stop accepting requests. It is especially important for keep-alive + connections.""" + if self._request_handler is None: + return + self._closing = True + + if timeout: + canceller = self._loop.call_later(timeout, + self._request_handler.cancel) + with suppress(asyncio.CancelledError): + yield from self._request_handler + canceller.cancel() + else: + self._request_handler.cancel() + + def connection_made(self, transport): + super().connection_made(transport) + + self._request_handler = ensure_future(self.start(), loop=self._loop) + + if self._tcp_keepalive: + tcp_keepalive(self, transport) + + def connection_lost(self, exc): + super().connection_lost(exc) + + self._closing = True + if self._request_handler is not None: + self._request_handler.cancel() + + def data_received(self, data): + super().data_received(data) + + # reading request + if not self._reading_request: + self._reading_request = True + + def keep_alive(self, val): + """Set keep-alive connection mode. + + :param bool val: new state. + """ + self._keepalive = val + + def log_access(self, message, environ, response, time): + if self.access_logger: + self.access_logger.log(message, environ, response, + self.transport, time) + + def log_debug(self, *args, **kw): + if self.debug: + self.logger.debug(*args, **kw) + + def log_exception(self, *args, **kw): + self.logger.exception(*args, **kw) + + @asyncio.coroutine + def start(self): + """Start processing of incoming requests. + + It reads request line, request headers and request payload, then + calls handle_request() method. Subclass has to override + handle_request(). start() handles various exceptions in request + or response handling. Connection is being closed always unless + keep_alive(True) specified. + """ + reader = self.reader + + try: + while not self._closing: + message = None + self._keepalive = False + self._request_count += 1 + self._reading_request = False + + payload = None + with Timeout(max(self._slow_request_timeout, + self._keepalive_timeout), + loop=self._loop): + # read HTTP request method + prefix = reader.set_parser(self._request_prefix) + yield from prefix.read() + + # start reading request + self._reading_request = True + + # start slow request timer + # read request headers + httpstream = reader.set_parser(self._request_parser) + message = yield from httpstream.read() + + # request may not have payload + try: + content_length = int( + message.headers.get(hdrs.CONTENT_LENGTH, 0)) + except ValueError: + raise errors.InvalidHeader(hdrs.CONTENT_LENGTH) from None + + if (content_length > 0 or + message.method == 'CONNECT' or + hdrs.SEC_WEBSOCKET_KEY1 in message.headers or + 'chunked' in message.headers.get( + hdrs.TRANSFER_ENCODING, '')): + payload = streams.FlowControlStreamReader( + reader, loop=self._loop) + reader.set_parser( + aiohttp.HttpPayloadParser(message), payload) + else: + payload = EMPTY_PAYLOAD + + yield from self.handle_request(message, payload) + + if payload and not payload.is_eof(): + self.log_debug('Uncompleted request.') + self._closing = True + else: + reader.unset_parser() + if not self._keepalive or not self._keepalive_timeout: + self._closing = True + + except asyncio.CancelledError: + self.log_debug( + 'Request handler cancelled.') + return + except asyncio.TimeoutError: + self.log_debug( + 'Request handler timed out.') + return + except errors.ClientDisconnectedError: + self.log_debug( + 'Ignored premature client disconnection #1.') + return + except errors.HttpProcessingError as exc: + yield from self.handle_error(exc.code, message, + None, exc, exc.headers, + exc.message) + except Exception as exc: + yield from self.handle_error(500, message, None, exc) + finally: + self._request_handler = None + if self.transport is None: + self.log_debug( + 'Ignored premature client disconnection #2.') + else: + self.transport.close() + + def handle_error(self, status=500, message=None, + payload=None, exc=None, headers=None, reason=None): + """Handle errors. + + Returns HTTP response with specific status code. Logs additional + information. It always closes current connection.""" + now = self._loop.time() + try: + if self.transport is None: + # client has been disconnected during writing. + return () + + if status == 500: + self.log_exception("Error handling request") + + try: + if reason is None or reason == '': + reason, msg = RESPONSES[status] + else: + msg = reason + except KeyError: + status = 500 + reason, msg = '???', '' + + if self.debug and exc is not None: + try: + tb = traceback.format_exc() + tb = html_escape(tb) + msg += '

Traceback:

\n
{}
'.format(tb) + except: + pass + + html = DEFAULT_ERROR_MESSAGE.format( + status=status, reason=reason, message=msg).encode('utf-8') + + response = aiohttp.Response(self.writer, status, close=True) + response.add_header(hdrs.CONTENT_TYPE, 'text/html; charset=utf-8') + response.add_header(hdrs.CONTENT_LENGTH, str(len(html))) + if headers is not None: + for name, value in headers: + response.add_header(name, value) + response.send_headers() + + response.write(html) + # disable CORK, enable NODELAY if needed + self.writer.set_tcp_nodelay(True) + drain = response.write_eof() + + self.log_access(message, None, response, self._loop.time() - now) + return drain + finally: + self.keep_alive(False) + + def handle_request(self, message, payload): + """Handle a single HTTP request. + + Subclass should override this method. By default it always + returns 404 response. + + :param message: Request headers + :type message: aiohttp.protocol.HttpRequestParser + :param payload: Request payload + :type payload: aiohttp.streams.FlowControlStreamReader + """ + now = self._loop.time() + response = aiohttp.Response( + self.writer, 404, http_version=message.version, close=True) + + body = b'Page Not Found!' + + response.add_header(hdrs.CONTENT_TYPE, 'text/plain') + response.add_header(hdrs.CONTENT_LENGTH, str(len(body))) + response.send_headers() + response.write(body) + drain = response.write_eof() + + self.keep_alive(False) + self.log_access(message, None, response, self._loop.time() - now) + + return drain diff --git a/venv/Lib/site-packages/aiohttp/signals.py b/venv/Lib/site-packages/aiohttp/signals.py index dda0dab4..5093bb84 100644 --- a/venv/Lib/site-packages/aiohttp/signals.py +++ b/venv/Lib/site-packages/aiohttp/signals.py @@ -1,34 +1,71 @@ -from aiohttp.frozenlist import FrozenList +import asyncio +from itertools import count -__all__ = ('Signal',) +class BaseSignal(list): -class Signal(FrozenList): + @asyncio.coroutine + def _send(self, *args, **kwargs): + for receiver in self: + res = receiver(*args, **kwargs) + if asyncio.iscoroutine(res) or isinstance(res, asyncio.Future): + yield from res + + def copy(self): + raise NotImplementedError("copy() is forbidden") + + def sort(self): + raise NotImplementedError("sort() is forbidden") + + +class Signal(BaseSignal): """Coroutine-based signal implementation. To connect a callback to a signal, use any list method. - Signals are fired using the send() coroutine, which takes named + Signals are fired using the :meth:`send` coroutine, which takes named arguments. """ - __slots__ = ('_owner',) - - def __init__(self, owner): + def __init__(self, app): super().__init__() - self._owner = owner - - def __repr__(self): - return ''.format(self._owner, - self.frozen, - list(self)) + self._app = app + klass = self.__class__ + self._name = klass.__module__ + ':' + klass.__qualname__ + self._pre = app.on_pre_signal + self._post = app.on_post_signal - async def send(self, *args, **kwargs): + @asyncio.coroutine + def send(self, *args, **kwargs): """ Sends data to all registered receivers. """ - if not self.frozen: - raise RuntimeError("Cannot send non-frozen signal.") + ordinal = None + debug = self._app._debug + if debug: + ordinal = self._pre.ordinal() + yield from self._pre.send(ordinal, self._name, *args, **kwargs) + yield from self._send(*args, **kwargs) + if debug: + yield from self._post.send(ordinal, self._name, *args, **kwargs) - for receiver in self: - await receiver(*args, **kwargs) # type: ignore + +class DebugSignal(BaseSignal): + + @asyncio.coroutine + def send(self, ordinal, name, *args, **kwargs): + yield from self._send(ordinal, name, *args, **kwargs) + + +class PreSignal(DebugSignal): + + def __init__(self): + super().__init__() + self._counter = count(1) + + def ordinal(self): + return next(self._counter) + + +class PostSignal(DebugSignal): + pass diff --git a/venv/Lib/site-packages/aiohttp/signals.pyi b/venv/Lib/site-packages/aiohttp/signals.pyi deleted file mode 100644 index efdbde73..00000000 --- a/venv/Lib/site-packages/aiohttp/signals.pyi +++ /dev/null @@ -1,17 +0,0 @@ -from typing import Any, Generic, TypeVar - -from aiohttp.frozenlist import FrozenList - -__all__ = ('Signal',) - - -_T = TypeVar('_T') - - -class Signal(FrozenList[_T], Generic[_T]): - - def __init__(self, owner: Any) -> None: ... - - def __repr__(self) -> str: ... - - async def send(self, *args: Any, **kwargs: Any) -> None: ... diff --git a/venv/Lib/site-packages/aiohttp/streams.py b/venv/Lib/site-packages/aiohttp/streams.py index c76685ce..fbe8d67e 100644 --- a/venv/Lib/site-packages/aiohttp/streams.py +++ b/venv/Lib/site-packages/aiohttp/streams.py @@ -1,92 +1,74 @@ import asyncio import collections -import warnings -from typing import List # noqa -from typing import Awaitable, Callable, Generic, Optional, Tuple, TypeVar +import functools +import sys +import traceback -from .base_protocol import BaseProtocol -from .helpers import BaseTimerContext, set_exception, set_result +from . import helpers from .log import internal_logger -try: # pragma: no cover - from typing import Deque # noqa -except ImportError: - from typing_extensions import Deque # noqa - __all__ = ( - 'EMPTY_PAYLOAD', 'EofStream', 'StreamReader', 'DataQueue', - 'FlowControlDataQueue') + 'EofStream', 'StreamReader', 'DataQueue', 'ChunksQueue', + 'FlowControlStreamReader', + 'FlowControlDataQueue', 'FlowControlChunksQueue') -DEFAULT_LIMIT = 2 ** 16 +PY_35 = sys.version_info >= (3, 5) +PY_352 = sys.version_info >= (3, 5, 2) -_T = TypeVar('_T') +EOF_MARKER = b'' +DEFAULT_LIMIT = 2 ** 16 class EofStream(Exception): """eof stream indication.""" -class AsyncStreamIterator(Generic[_T]): - - def __init__(self, read_func: Callable[[], Awaitable[_T]]) -> None: - self.read_func = read_func +if PY_35: + class AsyncStreamIterator: - def __aiter__(self) -> 'AsyncStreamIterator[_T]': - return self - - async def __anext__(self) -> _T: - try: - rv = await self.read_func() - except EofStream: - raise StopAsyncIteration # NOQA - if rv == b'': - raise StopAsyncIteration # NOQA - return rv + def __init__(self, read_func): + self.read_func = read_func + def __aiter__(self): + return self -class ChunkTupleAsyncStreamIterator: + if not PY_352: # pragma: no cover + __aiter__ = asyncio.coroutine(__aiter__) - def __init__(self, stream: 'StreamReader') -> None: - self._stream = stream - - def __aiter__(self) -> 'ChunkTupleAsyncStreamIterator': - return self - - async def __anext__(self) -> Tuple[bytes, bool]: - rv = await self._stream.readchunk() - if rv == (b'', False): - raise StopAsyncIteration # NOQA - return rv + @asyncio.coroutine + def __anext__(self): + try: + rv = yield from self.read_func() + except EofStream: + raise StopAsyncIteration # NOQA + if rv == EOF_MARKER: + raise StopAsyncIteration # NOQA + return rv class AsyncStreamReaderMixin: - def __aiter__(self) -> AsyncStreamIterator[bytes]: - return AsyncStreamIterator(self.readline) # type: ignore - - def iter_chunked(self, n: int) -> AsyncStreamIterator[bytes]: - """Returns an asynchronous iterator that yields chunks of size n. + if PY_35: + def __aiter__(self): + return AsyncStreamIterator(self.readline) - Python-3.5 available for Python 3.5+ only - """ - return AsyncStreamIterator(lambda: self.read(n)) # type: ignore + if not PY_352: # pragma: no cover + __aiter__ = asyncio.coroutine(__aiter__) - def iter_any(self) -> AsyncStreamIterator[bytes]: - """Returns an asynchronous iterator that yields all the available - data as soon as it is received + def iter_chunked(self, n): + """Returns an asynchronous iterator that yields chunks of size n. - Python-3.5 available for Python 3.5+ only - """ - return AsyncStreamIterator(self.readany) # type: ignore + Python-3.5 available for Python 3.5+ only + """ + return AsyncStreamIterator(lambda: self.read(n)) - def iter_chunks(self) -> ChunkTupleAsyncStreamIterator: - """Returns an asynchronous iterator that yields chunks of data - as they are received by the server. The yielded objects are tuples - of (bytes, bool) as returned by the StreamReader.readchunk method. + def iter_any(self): + """Returns an asynchronous iterator that yields slices of data + as they come. - Python-3.5 available for Python 3.5+ only - """ - return ChunkTupleAsyncStreamIterator(self) # type: ignore + Python-3.5 available for Python 3.5+ only + """ + return AsyncStreamIterator(self.readany) class StreamReader(AsyncStreamReaderMixin): @@ -105,182 +87,127 @@ class StreamReader(AsyncStreamReaderMixin): total_bytes = 0 - def __init__(self, protocol: BaseProtocol, - *, limit: int=DEFAULT_LIMIT, - timer: Optional[BaseTimerContext]=None, - loop: Optional[asyncio.AbstractEventLoop]=None) -> None: - self._protocol = protocol - self._low_water = limit - self._high_water = limit * 2 + def __init__(self, limit=DEFAULT_LIMIT, timeout=None, loop=None): + self._limit = limit if loop is None: loop = asyncio.get_event_loop() self._loop = loop - self._size = 0 - self._cursor = 0 - self._http_chunk_splits = None # type: Optional[List[int]] - self._buffer = collections.deque() # type: Deque[bytes] + self._buffer = collections.deque() + self._buffer_size = 0 self._buffer_offset = 0 self._eof = False - self._waiter = None # type: Optional[asyncio.Future[None]] - self._eof_waiter = None # type: Optional[asyncio.Future[None]] - self._exception = None # type: Optional[BaseException] - self._timer = timer - self._eof_callbacks = [] # type: List[Callable[[], None]] - - def __repr__(self) -> str: - info = [self.__class__.__name__] - if self._size: - info.append('%d bytes' % self._size) + self._waiter = None + self._canceller = None + self._eof_waiter = None + self._exception = None + self._timeout = timeout + + def __repr__(self): + info = ['StreamReader'] + if self._buffer_size: + info.append('%d bytes' % self._buffer_size) if self._eof: info.append('eof') - if self._low_water != DEFAULT_LIMIT: - info.append('low=%d high=%d' % (self._low_water, self._high_water)) + if self._limit != DEFAULT_LIMIT: + info.append('l=%d' % self._limit) if self._waiter: info.append('w=%r' % self._waiter) if self._exception: info.append('e=%r' % self._exception) return '<%s>' % ' '.join(info) - def exception(self) -> Optional[BaseException]: + def exception(self): return self._exception - def set_exception(self, exc: BaseException) -> None: + def set_exception(self, exc): self._exception = exc - self._eof_callbacks.clear() waiter = self._waiter if waiter is not None: self._waiter = None - set_exception(waiter, exc) + if not waiter.cancelled(): + waiter.set_exception(exc) - waiter = self._eof_waiter - if waiter is not None: - self._eof_waiter = None - set_exception(waiter, exc) + canceller = self._canceller + if canceller is not None: + self._canceller = None + canceller.cancel() - def on_eof(self, callback: Callable[[], None]) -> None: - if self._eof: - try: - callback() - except Exception: - internal_logger.exception('Exception in eof callback') - else: - self._eof_callbacks.append(callback) - - def feed_eof(self) -> None: + def feed_eof(self): self._eof = True waiter = self._waiter if waiter is not None: self._waiter = None - set_result(waiter, None) + if not waiter.cancelled(): + waiter.set_result(True) + + canceller = self._canceller + if canceller is not None: + self._canceller = None + canceller.cancel() waiter = self._eof_waiter if waiter is not None: self._eof_waiter = None - set_result(waiter, None) - - for cb in self._eof_callbacks: - try: - cb() - except Exception: - internal_logger.exception('Exception in eof callback') + if not waiter.cancelled(): + waiter.set_result(True) - self._eof_callbacks.clear() - - def is_eof(self) -> bool: + def is_eof(self): """Return True if 'feed_eof' was called.""" return self._eof - def at_eof(self) -> bool: + def at_eof(self): """Return True if the buffer is empty and 'feed_eof' was called.""" return self._eof and not self._buffer - async def wait_eof(self) -> None: + @asyncio.coroutine + def wait_eof(self): if self._eof: return assert self._eof_waiter is None - self._eof_waiter = self._loop.create_future() + self._eof_waiter = helpers.create_future(self._loop) try: - await self._eof_waiter + yield from self._eof_waiter finally: self._eof_waiter = None - def unread_data(self, data: bytes) -> None: + def unread_data(self, data): """ rollback reading some data from stream, inserting it to buffer head. """ - warnings.warn("unread_data() is deprecated " - "and will be removed in future releases (#3260)", - DeprecationWarning, - stacklevel=2) if not data: return if self._buffer_offset: self._buffer[0] = self._buffer[0][self._buffer_offset:] self._buffer_offset = 0 - self._size += len(data) - self._cursor -= len(data) self._buffer.appendleft(data) - self._eof_counter = 0 + self._buffer_size += len(data) - # TODO: size is ignored, remove the param later - def feed_data(self, data: bytes, size: int=0) -> None: + def feed_data(self, data): assert not self._eof, 'feed_data after feed_eof' if not data: return - self._size += len(data) self._buffer.append(data) + self._buffer_size += len(data) self.total_bytes += len(data) waiter = self._waiter if waiter is not None: self._waiter = None - set_result(waiter, None) - - if (self._size > self._high_water and - not self._protocol._reading_paused): - self._protocol.pause_reading() - - def begin_http_chunk_receiving(self) -> None: - if self._http_chunk_splits is None: - if self.total_bytes: - raise RuntimeError("Called begin_http_chunk_receiving when" - "some data was already fed") - self._http_chunk_splits = [] - - def end_http_chunk_receiving(self) -> None: - if self._http_chunk_splits is None: - raise RuntimeError("Called end_chunk_receiving without calling " - "begin_chunk_receiving first") - - # self._http_chunk_splits contains logical byte offsets from start of - # the body transfer. Each offset is the offset of the end of a chunk. - # "Logical" means bytes, accessible for a user. - # If no chunks containig logical data were received, current position - # is difinitely zero. - pos = self._http_chunk_splits[-1] if self._http_chunk_splits else 0 - - if self.total_bytes == pos: - # We should not add empty chunks here. So we check for that. - # Note, when chunked + gzip is used, we can receive a chunk - # of compressed data, but that data may not be enough for gzip FSM - # to yield any uncompressed data. That's why current position may - # not change after receiving a chunk. - return + if not waiter.cancelled(): + waiter.set_result(False) - self._http_chunk_splits.append(self.total_bytes) + canceller = self._canceller + if canceller is not None: + self._canceller = None + canceller.cancel() - # wake up readchunk when end of http chunk received - waiter = self._waiter - if waiter is not None: - self._waiter = None - set_result(waiter, None) - - async def _wait(self, func_name: str) -> None: + @asyncio.coroutine + def _wait(self, func_name): # StreamReader uses a future to link the protocol feed_data() method # to a read coroutine. Running two read coroutines at the same time # would have an unexpected behaviour. It would not possible to know @@ -288,18 +215,21 @@ class StreamReader(AsyncStreamReaderMixin): if self._waiter is not None: raise RuntimeError('%s() called while another coroutine is ' 'already waiting for incoming data' % func_name) - - waiter = self._waiter = self._loop.create_future() + waiter = self._waiter = helpers.create_future(self._loop) + if self._timeout: + self._canceller = self._loop.call_later(self._timeout, + self.set_exception, + asyncio.TimeoutError()) try: - if self._timer: - with self._timer: - await waiter - else: - await waiter + yield from waiter finally: self._waiter = None + if self._canceller is not None: + self._canceller.cancel() + self._canceller = None - async def readline(self) -> bytes: + @asyncio.coroutine + def readline(self): if self._exception is not None: raise self._exception @@ -318,18 +248,19 @@ class StreamReader(AsyncStreamReaderMixin): if ichar: not_enough = False - if line_size > self._high_water: + if line_size > self._limit: raise ValueError('Line is too long') if self._eof: break if not_enough: - await self._wait('readline') + yield from self._wait('readline') return b''.join(line) - async def read(self, n: int=-1) -> bytes: + @asyncio.coroutine + def read(self, n=-1): if self._exception is not None: raise self._exception @@ -341,12 +272,13 @@ class StreamReader(AsyncStreamReaderMixin): if self._eof and not self._buffer: self._eof_counter = getattr(self, '_eof_counter', 0) + 1 if self._eof_counter > 5: + stack = traceback.format_stack() internal_logger.warning( 'Multiple access to StreamReader in eof state, ' - 'might be infinite loop.', stack_info=True) + 'might be infinite loop: \n%s', stack) if not n: - return b'' + return EOF_MARKER if n < 0: # This used to just loop creating a new waiter hoping to @@ -355,83 +287,50 @@ class StreamReader(AsyncStreamReaderMixin): # bytes. So just call self.readany() until EOF. blocks = [] while True: - block = await self.readany() + block = yield from self.readany() if not block: break blocks.append(block) return b''.join(blocks) - # TODO: should be `if` instead of `while` - # because waiter maybe triggered on chunk end, - # without feeding any data - while not self._buffer and not self._eof: - await self._wait('read') + if not self._buffer and not self._eof: + yield from self._wait('read') return self._read_nowait(n) - async def readany(self) -> bytes: + @asyncio.coroutine + def readany(self): if self._exception is not None: raise self._exception - # TODO: should be `if` instead of `while` - # because waiter maybe triggered on chunk end, - # without feeding any data - while not self._buffer and not self._eof: - await self._wait('readany') + if not self._buffer and not self._eof: + yield from self._wait('readany') return self._read_nowait(-1) - async def readchunk(self) -> Tuple[bytes, bool]: - """Returns a tuple of (data, end_of_http_chunk). When chunked transfer - encoding is used, end_of_http_chunk is a boolean indicating if the end - of the data corresponds to the end of a HTTP chunk , otherwise it is - always False. - """ - while True: - if self._exception is not None: - raise self._exception - - while self._http_chunk_splits: - pos = self._http_chunk_splits.pop(0) - if pos == self._cursor: - return (b"", True) - if pos > self._cursor: - return (self._read_nowait(pos-self._cursor), True) - internal_logger.warning('Skipping HTTP chunk end due to data ' - 'consumption beyond chunk boundary') - - if self._buffer: - return (self._read_nowait_chunk(-1), False) - # return (self._read_nowait(-1), False) - - if self._eof: - # Special case for signifying EOF. - # (b'', True) is not a final return value actually. - return (b'', False) - - await self._wait('readchunk') - - async def readexactly(self, n: int) -> bytes: + @asyncio.coroutine + def readexactly(self, n): if self._exception is not None: raise self._exception - blocks = [] # type: List[bytes] + blocks = [] while n > 0: - block = await self.read(n) + block = yield from self.read(n) if not block: partial = b''.join(blocks) - raise asyncio.IncompleteReadError( + raise asyncio.streams.IncompleteReadError( partial, len(partial) + n) blocks.append(block) n -= len(block) return b''.join(blocks) - def read_nowait(self, n: int=-1) -> bytes: + def read_nowait(self, n=-1): # default was changed to be consistent with .read(-1) # # I believe the most users don't know about the method and # they are not affected. + assert n is not None, "n should be -1" if self._exception is not None: raise self._exception @@ -441,7 +340,7 @@ class StreamReader(AsyncStreamReaderMixin): return self._read_nowait(n) - def _read_nowait_chunk(self, n: int) -> bytes: + def _read_nowait_chunk(self, n): first_buffer = self._buffer[0] offset = self._buffer_offset if n != -1 and len(first_buffer) - offset > n: @@ -456,20 +355,10 @@ class StreamReader(AsyncStreamReaderMixin): else: data = self._buffer.popleft() - self._size -= len(data) - self._cursor += len(data) - - chunk_splits = self._http_chunk_splits - # Prevent memory leak: drop useless chunk splits - while chunk_splits and chunk_splits[0] < self._cursor: - chunk_splits.pop(0) - - if self._size < self._low_water and self._protocol._reading_paused: - self._protocol.resume_reading() + self._buffer_size -= len(data) return data - def _read_nowait(self, n: int) -> bytes: - """ Read not more than n bytes, or whole buffer is n == -1 """ + def _read_nowait(self, n): chunks = [] while self._buffer: @@ -480,115 +369,111 @@ class StreamReader(AsyncStreamReaderMixin): if n == 0: break - return b''.join(chunks) if chunks else b'' + return b''.join(chunks) if chunks else EOF_MARKER class EmptyStreamReader(AsyncStreamReaderMixin): - def exception(self) -> Optional[BaseException]: + def exception(self): return None - def set_exception(self, exc: BaseException) -> None: + def set_exception(self, exc): pass - def on_eof(self, callback: Callable[[], None]) -> None: - try: - callback() - except Exception: - internal_logger.exception('Exception in eof callback') - - def feed_eof(self) -> None: + def feed_eof(self): pass - def is_eof(self) -> bool: + def is_eof(self): return True - def at_eof(self) -> bool: + def at_eof(self): return True - async def wait_eof(self) -> None: + @asyncio.coroutine + def wait_eof(self): return - def feed_data(self, data: bytes, n: int=0) -> None: + def feed_data(self, data): pass - async def readline(self) -> bytes: - return b'' - - async def read(self, n: int=-1) -> bytes: - return b'' - - async def readany(self) -> bytes: - return b'' + @asyncio.coroutine + def readline(self): + return EOF_MARKER - async def readchunk(self) -> Tuple[bytes, bool]: - return (b'', True) + @asyncio.coroutine + def read(self, n=-1): + return EOF_MARKER - async def readexactly(self, n: int) -> bytes: - raise asyncio.IncompleteReadError(b'', n) + @asyncio.coroutine + def readany(self): + return EOF_MARKER - def read_nowait(self) -> bytes: - return b'' + @asyncio.coroutine + def readexactly(self, n): + raise asyncio.streams.IncompleteReadError(b'', n) + def read_nowait(self): + return EOF_MARKER -EMPTY_PAYLOAD = EmptyStreamReader() - -class DataQueue(Generic[_T]): +class DataQueue: """DataQueue is a general-purpose blocking queue with one reader.""" - def __init__(self, loop: asyncio.AbstractEventLoop) -> None: + def __init__(self, *, loop=None): self._loop = loop self._eof = False - self._waiter = None # type: Optional[asyncio.Future[None]] - self._exception = None # type: Optional[BaseException] + self._waiter = None + self._exception = None self._size = 0 - self._buffer = collections.deque() # type: Deque[Tuple[_T, int]] - - def __len__(self) -> int: - return len(self._buffer) + self._buffer = collections.deque() - def is_eof(self) -> bool: + def is_eof(self): return self._eof - def at_eof(self) -> bool: + def at_eof(self): return self._eof and not self._buffer - def exception(self) -> Optional[BaseException]: + def exception(self): return self._exception - def set_exception(self, exc: BaseException) -> None: - self._eof = True + def set_exception(self, exc): self._exception = exc waiter = self._waiter if waiter is not None: self._waiter = None - set_exception(waiter, exc) + if not waiter.done(): + waiter.set_exception(exc) - def feed_data(self, data: _T, size: int=0) -> None: + def feed_data(self, data, size=0): self._size += size self._buffer.append((data, size)) waiter = self._waiter if waiter is not None: self._waiter = None - set_result(waiter, None) + if not waiter.cancelled(): + waiter.set_result(True) - def feed_eof(self) -> None: + def feed_eof(self): self._eof = True waiter = self._waiter if waiter is not None: self._waiter = None - set_result(waiter, None) + if not waiter.cancelled(): + waiter.set_result(False) - async def read(self) -> _T: + @asyncio.coroutine + def read(self): if not self._buffer and not self._eof: + if self._exception is not None: + raise self._exception + assert not self._waiter - self._waiter = self._loop.create_future() + self._waiter = helpers.create_future(self._loop) try: - await self._waiter + yield from self._waiter except (asyncio.CancelledError, asyncio.TimeoutError): self._waiter = None raise @@ -603,32 +488,185 @@ class DataQueue(Generic[_T]): else: raise EofStream - def __aiter__(self) -> AsyncStreamIterator[_T]: - return AsyncStreamIterator(self.read) + if PY_35: + def __aiter__(self): + return AsyncStreamIterator(self.read) + + if not PY_352: # pragma: no cover + __aiter__ = asyncio.coroutine(__aiter__) + + +class ChunksQueue(DataQueue): + """Like a :class:`DataQueue`, but for binary chunked data transfer.""" + + @asyncio.coroutine + def read(self): + try: + return (yield from super().read()) + except EofStream: + return EOF_MARKER + + readany = read + + +def maybe_resume(func): + + if asyncio.iscoroutinefunction(func): + @asyncio.coroutine + @functools.wraps(func) + def wrapper(self, *args, **kw): + result = yield from func(self, *args, **kw) + self._check_buffer_size() + return result + else: + @functools.wraps(func) + def wrapper(self, *args, **kw): + result = func(self, *args, **kw) + self._check_buffer_size() + return result + + return wrapper + + +class FlowControlStreamReader(StreamReader): + + def __init__(self, stream, limit=DEFAULT_LIMIT, *args, **kwargs): + super().__init__(*args, **kwargs) + + self._stream = stream + self._b_limit = limit * 2 + + # resume transport reading + if stream.paused: + try: + self._stream.transport.resume_reading() + except (AttributeError, NotImplementedError): + pass + else: + self._stream.paused = False + + def _check_buffer_size(self): + if self._stream.paused: + if self._buffer_size < self._b_limit: + try: + self._stream.transport.resume_reading() + except (AttributeError, NotImplementedError): + pass + else: + self._stream.paused = False + else: + if self._buffer_size > self._b_limit: + try: + self._stream.transport.pause_reading() + except (AttributeError, NotImplementedError): + pass + else: + self._stream.paused = True + + def feed_data(self, data, size=0): + has_waiter = self._waiter is not None and not self._waiter.cancelled() + + super().feed_data(data) + + if (not self._stream.paused and + not has_waiter and self._buffer_size > self._b_limit): + try: + self._stream.transport.pause_reading() + except (AttributeError, NotImplementedError): + pass + else: + self._stream.paused = True + + @maybe_resume + @asyncio.coroutine + def read(self, n=-1): + return (yield from super().read(n)) + @maybe_resume + @asyncio.coroutine + def readline(self): + return (yield from super().readline()) -class FlowControlDataQueue(DataQueue[_T]): + @maybe_resume + @asyncio.coroutine + def readany(self): + return (yield from super().readany()) + + @maybe_resume + @asyncio.coroutine + def readexactly(self, n): + return (yield from super().readexactly(n)) + + @maybe_resume + def read_nowait(self, n=-1): + return super().read_nowait(n) + + +class FlowControlDataQueue(DataQueue): """FlowControlDataQueue resumes and pauses an underlying stream. It is a destination for parsed data.""" - def __init__(self, protocol: BaseProtocol, *, - limit: int=DEFAULT_LIMIT, - loop: asyncio.AbstractEventLoop) -> None: + def __init__(self, stream, *, limit=DEFAULT_LIMIT, loop=None): super().__init__(loop=loop) - self._protocol = protocol + self._stream = stream self._limit = limit * 2 - def feed_data(self, data: _T, size: int=0) -> None: + # resume transport reading + if stream.paused: + try: + self._stream.transport.resume_reading() + except (AttributeError, NotImplementedError): + pass + else: + self._stream.paused = False + + def feed_data(self, data, size): + has_waiter = self._waiter is not None and not self._waiter.cancelled() + super().feed_data(data, size) - if self._size > self._limit and not self._protocol._reading_paused: - self._protocol.pause_reading() + if (not self._stream.paused and + not has_waiter and self._size > self._limit): + try: + self._stream.transport.pause_reading() + except (AttributeError, NotImplementedError): + pass + else: + self._stream.paused = True + + @asyncio.coroutine + def read(self): + result = yield from super().read() + + if self._stream.paused: + if self._size < self._limit: + try: + self._stream.transport.resume_reading() + except (AttributeError, NotImplementedError): + pass + else: + self._stream.paused = False + else: + if self._size > self._limit: + try: + self._stream.transport.pause_reading() + except (AttributeError, NotImplementedError): + pass + else: + self._stream.paused = True + + return result + + +class FlowControlChunksQueue(FlowControlDataQueue): - async def read(self) -> _T: + @asyncio.coroutine + def read(self): try: - return await super().read() - finally: - if self._size < self._limit and self._protocol._reading_paused: - self._protocol.resume_reading() + return (yield from super().read()) + except EofStream: + return EOF_MARKER + + readany = read diff --git a/venv/Lib/site-packages/aiohttp/tcp_helpers.py b/venv/Lib/site-packages/aiohttp/tcp_helpers.py deleted file mode 100644 index 440c1167..00000000 --- a/venv/Lib/site-packages/aiohttp/tcp_helpers.py +++ /dev/null @@ -1,63 +0,0 @@ -"""Helper methods to tune a TCP connection""" - -import asyncio -import socket -from contextlib import suppress -from typing import Optional # noqa - -__all__ = ('tcp_keepalive', 'tcp_nodelay', 'tcp_cork') - - -if hasattr(socket, 'TCP_CORK'): # pragma: no cover - CORK = socket.TCP_CORK # type: Optional[int] -elif hasattr(socket, 'TCP_NOPUSH'): # pragma: no cover - CORK = socket.TCP_NOPUSH # type: ignore -else: # pragma: no cover - CORK = None - - -if hasattr(socket, 'SO_KEEPALIVE'): - def tcp_keepalive(transport: asyncio.Transport) -> None: - sock = transport.get_extra_info('socket') - if sock is not None: - sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) -else: - def tcp_keepalive( - transport: asyncio.Transport) -> None: # pragma: no cover - pass - - -def tcp_nodelay(transport: asyncio.Transport, value: bool) -> None: - sock = transport.get_extra_info('socket') - - if sock is None: - return - - if sock.family not in (socket.AF_INET, socket.AF_INET6): - return - - value = bool(value) - - # socket may be closed already, on windows OSError get raised - with suppress(OSError): - sock.setsockopt( - socket.IPPROTO_TCP, socket.TCP_NODELAY, value) - - -def tcp_cork(transport: asyncio.Transport, value: bool) -> None: - sock = transport.get_extra_info('socket') - - if CORK is None: - return - - if sock is None: - return - - if sock.family not in (socket.AF_INET, socket.AF_INET6): - return - - value = bool(value) - - with suppress(OSError): - sock.setsockopt( - socket.IPPROTO_TCP, CORK, value) diff --git a/venv/Lib/site-packages/aiohttp/test_utils.py b/venv/Lib/site-packages/aiohttp/test_utils.py index ebfa9732..8cffb3d6 100644 --- a/venv/Lib/site-packages/aiohttp/test_utils.py +++ b/venv/Lib/site-packages/aiohttp/test_utils.py @@ -4,157 +4,67 @@ import asyncio import contextlib import functools import gc -import inspect import socket import sys import unittest -from abc import ABC, abstractmethod -from types import TracebackType -from typing import ( # noqa - TYPE_CHECKING, - Any, - Callable, - Iterator, - List, - Optional, - Type, - Union, -) from unittest import mock -from multidict import CIMultiDict, CIMultiDictProxy -from yarl import URL +from multidict import CIMultiDict import aiohttp -from aiohttp.client import ( - ClientResponse, - _RequestContextManager, - _WSRequestContextManager, -) from . import ClientSession, hdrs -from .abc import AbstractCookieJar -from .client_reqrep import ClientResponse # noqa -from .client_ws import ClientWebSocketResponse # noqa from .helpers import sentinel -from .http import HttpVersion, RawRequestMessage +from .protocol import HttpVersion, RawRequestMessage from .signals import Signal -from .web import ( - Application, - AppRunner, - BaseRunner, - Request, - Server, - ServerRunner, - SockSite, - UrlMappingMatchInfo, -) -from .web_protocol import _RequestHandler +from .web import Application, Request -if TYPE_CHECKING: # pragma: no cover - from ssl import SSLContext -else: - SSLContext = None +PY_35 = sys.version_info >= (3, 5) -def get_unused_port_socket(host: str) -> socket.socket: - return get_port_socket(host, 0) - - -def get_port_socket(host: str, port: int) -> socket.socket: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.bind((host, port)) - return s +def run_briefly(loop): + @asyncio.coroutine + def once(): + pass + t = asyncio.Task(once(), loop=loop) + loop.run_until_complete(t) -def unused_port() -> int: +def unused_port(): """Return a port that is unused on the current host.""" with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(('127.0.0.1', 0)) return s.getsockname()[1] -class BaseTestServer(ABC): - __test__ = False - - def __init__(self, - *, - scheme: Union[str, object]=sentinel, - loop: Optional[asyncio.AbstractEventLoop]=None, - host: str='127.0.0.1', - port: Optional[int]=None, - skip_url_asserts: bool=False, - **kwargs: Any) -> None: - self._loop = loop - self.runner = None # type: Optional[BaseRunner] - self._root = None # type: Optional[URL] +class TestServer: + def __init__(self, app, *, scheme="http", host='127.0.0.1'): + self.app = app + self._loop = app.loop + self.port = None + self.server = None + self.handler = None + self._root = None self.host = host - self.port = port - self._closed = False self.scheme = scheme - self.skip_url_asserts = skip_url_asserts + self._closed = False - async def start_server(self, - loop: Optional[asyncio.AbstractEventLoop]=None, - **kwargs: Any) -> None: - if self.runner: + @asyncio.coroutine + def start_server(self, **kwargs): + if self.server: return - self._loop = loop - self._ssl = kwargs.pop('ssl', None) - self.runner = await self._make_runner(**kwargs) - await self.runner.setup() - if not self.port: - self.port = 0 - _sock = get_port_socket(self.host, self.port) - self.host, self.port = _sock.getsockname()[:2] - site = SockSite(self.runner, sock=_sock, ssl_context=self._ssl) - await site.start() - server = site._server - assert server is not None - sockets = server.sockets - assert sockets is not None - self.port = sockets[0].getsockname()[1] - if self.scheme is sentinel: - if self._ssl: - scheme = 'https' - else: - scheme = 'http' - self.scheme = scheme - self._root = URL('{}://{}:{}'.format(self.scheme, - self.host, - self.port)) - - @abstractmethod # pragma: no cover - async def _make_runner(self, **kwargs: Any) -> BaseRunner: - pass - - def make_url(self, path: str) -> URL: - assert self._root is not None - url = URL(path) - if not self.skip_url_asserts: - assert not url.is_absolute() - return self._root.join(url) - else: - return URL(str(self._root) + path) - - @property - def started(self) -> bool: - return self.runner is not None - - @property - def closed(self) -> bool: - return self._closed - - @property - def handler(self) -> Server: - # for backward compatibility - # web.Server instance - runner = self.runner - assert runner is not None - assert runner.server is not None - return runner.server - - async def close(self) -> None: + self.port = unused_port() + self._root = '{}://{}:{}'.format(self.scheme, self.host, self.port) + self.handler = self.app.make_handler(**kwargs) + self.server = yield from self._loop.create_server(self.handler, + self.host, + self.port) + + def make_url(self, path): + return self._root + path + + @asyncio.coroutine + def close(self): """Close all fixtures created by the test client. After that point, the TestClient is no longer usable. @@ -166,115 +76,99 @@ class BaseTestServer(ABC): exit when used as a context manager. """ - if self.started and not self.closed: - assert self.runner is not None - await self.runner.cleanup() + if self.server is not None and not self._closed: + self.server.close() + yield from self.server.wait_closed() + yield from self.app.shutdown() + yield from self.handler.finish_connections() + yield from self.app.cleanup() self._root = None self.port = None self._closed = True - def __enter__(self) -> None: - raise TypeError("Use async with instead") - - def __exit__(self, - exc_type: Optional[Type[BaseException]], - exc_value: Optional[BaseException], - traceback: Optional[TracebackType]) -> None: - # __exit__ should exist in pair with __enter__ but never executed - pass # pragma: no cover - - async def __aenter__(self) -> 'BaseTestServer': - await self.start_server(loop=self._loop) + def __enter__(self): + self._loop.run_until_complete(self.start_server()) return self - async def __aexit__(self, - exc_type: Optional[Type[BaseException]], - exc_value: Optional[BaseException], - traceback: Optional[TracebackType]) -> None: - await self.close() + def __exit__(self, exc_type, exc_value, traceback): + self._loop.run_until_complete(self.close()) + if PY_35: + @asyncio.coroutine + def __aenter__(self): + yield from self.start_server() + return self -class TestServer(BaseTestServer): + @asyncio.coroutine + def __aexit__(self, exc_type, exc_value, traceback): + yield from self.close() - def __init__(self, app: Application, *, - scheme: Union[str, object]=sentinel, - host: str='127.0.0.1', - port: Optional[int]=None, - **kwargs: Any): - self.app = app - super().__init__(scheme=scheme, host=host, port=port, **kwargs) - - async def _make_runner(self, **kwargs: Any) -> BaseRunner: - return AppRunner(self.app, **kwargs) +class TestClient: + """ + A test client implementation, for a aiohttp.web.Application. -class RawTestServer(BaseTestServer): + :param app: the aiohttp.web application passed to create_test_server - def __init__(self, handler: _RequestHandler, *, - scheme: Union[str, object]=sentinel, - host: str='127.0.0.1', - port: Optional[int]=None, - **kwargs: Any) -> None: - self._handler = handler - super().__init__(scheme=scheme, host=host, port=port, **kwargs) + :type app: aiohttp.web.Application - async def _make_runner(self, - debug: bool=True, - **kwargs: Any) -> ServerRunner: - srv = Server( - self._handler, loop=self._loop, debug=debug, **kwargs) - return ServerRunner(srv, debug=debug, **kwargs) + :param protocol: http or https + :type protocol: str -class TestClient: + TestClient can also be used as a contextmanager, returning + the instance of itself instantiated. """ - A test client implementation. - To write functional tests for aiohttp based servers. - - """ - __test__ = False - - def __init__(self, server: BaseTestServer, *, - cookie_jar: Optional[AbstractCookieJar]=None, - loop: Optional[asyncio.AbstractEventLoop]=None, - **kwargs: Any) -> None: - if not isinstance(server, BaseTestServer): - raise TypeError("server must be TestServer " - "instance, found type: %r" % type(server)) - self._server = server - self._loop = loop - if cookie_jar is None: - cookie_jar = aiohttp.CookieJar(unsafe=True, loop=loop) - self._session = ClientSession(loop=loop, - cookie_jar=cookie_jar, - **kwargs) + def __init__(self, app_or_server, *, scheme=sentinel, host=sentinel): + if isinstance(app_or_server, TestServer): + if scheme is not sentinel or host is not sentinel: + raise ValueError("scheme and host are mutable exclusive " + "with TestServer parameter") + self._server = app_or_server + elif isinstance(app_or_server, Application): + scheme = "http" if scheme is sentinel else scheme + host = '127.0.0.1' if host is sentinel else host + self._server = TestServer(app_or_server, + scheme=scheme, host=host) + else: + raise TypeError("app_or_server should be either web.Application " + "or TestServer instance") + self._loop = self._server.app.loop + self._session = ClientSession( + loop=self._loop, + cookie_jar=aiohttp.CookieJar(unsafe=True, + loop=self._loop)) self._closed = False - self._responses = [] # type: List[ClientResponse] - self._websockets = [] # type: List[ClientWebSocketResponse] + self._responses = [] - async def start_server(self) -> None: - await self._server.start_server(loop=self._loop) + @asyncio.coroutine + def start_server(self): + yield from self._server.start_server() @property - def host(self) -> str: + def app(self): + return self._server.app + + @property + def host(self): return self._server.host @property - def port(self) -> Optional[int]: + def port(self): return self._server.port @property - def server(self) -> BaseTestServer: - return self._server + def handler(self): + return self._server.handler @property - def app(self) -> Application: - return getattr(self._server, "app", None) + def server(self): + return self._server.server @property - def session(self) -> ClientSession: - """An internal aiohttp.ClientSession. + def session(self): + """A raw handler to the aiohttp.ClientSession. Unlike the methods on the TestClient, client session requests do not automatically include the host in the url queried, and @@ -283,91 +177,65 @@ class TestClient: """ return self._session - def make_url(self, path: str) -> URL: + def make_url(self, path): return self._server.make_url(path) - async def _request(self, method: str, path: str, - **kwargs: Any) -> ClientResponse: - resp = await self._session.request( - method, self.make_url(path), **kwargs - ) - # save it to close later - self._responses.append(resp) - return resp + @asyncio.coroutine + def request(self, method, path, *args, **kwargs): + """Routes a request to the http server. - def request(self, method: str, path: str, - **kwargs: Any) -> _RequestContextManager: - """Routes a request to tested http server. - - The interface is identical to aiohttp.ClientSession.request, + The interface is identical to asyncio.ClientSession.request, except the loop kwarg is overridden by the instance used by the - test server. + application. """ - return _RequestContextManager( - self._request(method, path, **kwargs) + resp = yield from self._session.request( + method, self.make_url(path), *args, **kwargs ) + # save it to close later + self._responses.append(resp) + return resp - def get(self, path: str, **kwargs: Any) -> _RequestContextManager: + def get(self, path, *args, **kwargs): """Perform an HTTP GET request.""" - return _RequestContextManager( - self._request(hdrs.METH_GET, path, **kwargs) - ) + return self.request(hdrs.METH_GET, path, *args, **kwargs) - def post(self, path: str, **kwargs: Any) -> _RequestContextManager: + def post(self, path, *args, **kwargs): """Perform an HTTP POST request.""" - return _RequestContextManager( - self._request(hdrs.METH_POST, path, **kwargs) - ) + return self.request(hdrs.METH_POST, path, *args, **kwargs) - def options(self, path: str, **kwargs: Any) -> _RequestContextManager: + def options(self, path, *args, **kwargs): """Perform an HTTP OPTIONS request.""" - return _RequestContextManager( - self._request(hdrs.METH_OPTIONS, path, **kwargs) - ) + return self.request(hdrs.METH_OPTIONS, path, *args, **kwargs) - def head(self, path: str, **kwargs: Any) -> _RequestContextManager: + def head(self, path, *args, **kwargs): """Perform an HTTP HEAD request.""" - return _RequestContextManager( - self._request(hdrs.METH_HEAD, path, **kwargs) - ) + return self.request(hdrs.METH_HEAD, path, *args, **kwargs) - def put(self, path: str, **kwargs: Any) -> _RequestContextManager: + def put(self, path, *args, **kwargs): """Perform an HTTP PUT request.""" - return _RequestContextManager( - self._request(hdrs.METH_PUT, path, **kwargs) - ) + return self.request(hdrs.METH_PUT, path, *args, **kwargs) - def patch(self, path: str, **kwargs: Any) -> _RequestContextManager: + def patch(self, path, *args, **kwargs): """Perform an HTTP PATCH request.""" - return _RequestContextManager( - self._request(hdrs.METH_PATCH, path, **kwargs) - ) + return self.request(hdrs.METH_PATCH, path, *args, **kwargs) - def delete(self, path: str, **kwargs: Any) -> _RequestContextManager: + def delete(self, path, *args, **kwargs): """Perform an HTTP PATCH request.""" - return _RequestContextManager( - self._request(hdrs.METH_DELETE, path, **kwargs) - ) + return self.request(hdrs.METH_DELETE, path, *args, **kwargs) - def ws_connect(self, path: str, **kwargs: Any) -> _WSRequestContextManager: + def ws_connect(self, path, *args, **kwargs): """Initiate websocket connection. - The api corresponds to aiohttp.ClientSession.ws_connect. + The api is identical to aiohttp.ClientSession.ws_connect. """ - return _WSRequestContextManager( - self._ws_connect(path, **kwargs) + return self._session.ws_connect( + self.make_url(path), *args, **kwargs ) - async def _ws_connect(self, path: str, - **kwargs: Any) -> ClientWebSocketResponse: - ws = await self._session.ws_connect( - self.make_url(path), **kwargs) - self._websockets.append(ws) - return ws - - async def close(self) -> None: + @asyncio.coroutine + def close(self): """Close all fixtures created by the test client. After that point, the TestClient is no longer usable. @@ -382,31 +250,26 @@ class TestClient: if not self._closed: for resp in self._responses: resp.close() - for ws in self._websockets: - await ws.close() - await self._session.close() - await self._server.close() + yield from self._session.close() + yield from self._server.close() self._closed = True - def __enter__(self) -> None: - raise TypeError("Use async with instead") + def __enter__(self): + self._loop.run_until_complete(self.start_server()) + return self - def __exit__(self, - exc_type: Optional[Type[BaseException]], - exc: Optional[BaseException], - tb: Optional[TracebackType]) -> None: - # __exit__ should exist in pair with __enter__ but never executed - pass # pragma: no cover + def __exit__(self, exc_type, exc_value, traceback): + self._loop.run_until_complete(self.close()) - async def __aenter__(self) -> 'TestClient': - await self.start_server() - return self + if PY_35: + @asyncio.coroutine + def __aenter__(self): + yield from self.start_server() + return self - async def __aexit__(self, - exc_type: Optional[Type[BaseException]], - exc: Optional[BaseException], - tb: Optional[TracebackType]) -> None: - await self.close() + @asyncio.coroutine + def __aexit__(self, exc_type, exc_value, traceback): + yield from self.close() class AioHTTPTestCase(unittest.TestCase): @@ -419,62 +282,35 @@ class AioHTTPTestCase(unittest.TestCase): * self.loop (asyncio.BaseEventLoop): the event loop in which the application and server are running. * self.app (aiohttp.web.Application): the application returned by - self.get_application() + self.get_app() Note that the TestClient's methods are asynchronous: you have to execute function on the test client using asynchronous methods. """ - async def get_application(self) -> Application: + def get_app(self, loop): """ This method should be overridden to return the aiohttp.web.Application object to test. + :param loop: the event_loop to use + :type loop: asyncio.BaseEventLoop """ - return self.get_app() - - def get_app(self) -> Application: - """Obsolete method used to constructing web application. - - Use .get_application() coroutine instead - - """ - raise RuntimeError("Did you forget to define get_application()?") + pass # pragma: no cover - def setUp(self) -> None: + def setUp(self): self.loop = setup_test_loop() - - self.app = self.loop.run_until_complete(self.get_application()) - self.server = self.loop.run_until_complete(self.get_server(self.app)) - self.client = self.loop.run_until_complete( - self.get_client(self.server)) - + self.app = self.get_app(self.loop) + self.client = TestClient(self.app) self.loop.run_until_complete(self.client.start_server()) - self.loop.run_until_complete(self.setUpAsync()) - - async def setUpAsync(self) -> None: - pass - - def tearDown(self) -> None: - self.loop.run_until_complete(self.tearDownAsync()) + def tearDown(self): self.loop.run_until_complete(self.client.close()) teardown_test_loop(self.loop) - async def tearDownAsync(self) -> None: - pass - - async def get_server(self, app: Application) -> TestServer: - """Return a TestServer instance.""" - return TestServer(app, loop=self.loop) - async def get_client(self, server: TestServer) -> TestClient: - """Return a TestClient instance.""" - return TestClient(server, loop=self.loop) - - -def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: +def unittest_run_loop(func): """A decorator dedicated to use with asynchronous methods of an AioHTTPTestCase. @@ -482,32 +318,25 @@ def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: the self.loop of the AioHTTPTestCase. """ - @functools.wraps(func, *args, **kwargs) - def new_func(self: Any, *inner_args: Any, **inner_kwargs: Any) -> Any: - return self.loop.run_until_complete( - func(self, *inner_args, **inner_kwargs)) + @functools.wraps(func) + def new_func(self): + return self.loop.run_until_complete(func(self)) return new_func -_LOOP_FACTORY = Callable[[], asyncio.AbstractEventLoop] - - @contextlib.contextmanager -def loop_context(loop_factory: _LOOP_FACTORY=asyncio.new_event_loop, - fast: bool=False) -> Iterator[asyncio.AbstractEventLoop]: +def loop_context(loop_factory=asyncio.new_event_loop): """A contextmanager that creates an event_loop, for test purposes. Handles the creation and cleanup of a test loop. """ loop = setup_test_loop(loop_factory) yield loop - teardown_test_loop(loop, fast=fast) + teardown_test_loop(loop) -def setup_test_loop( - loop_factory: _LOOP_FACTORY=asyncio.new_event_loop -) -> asyncio.AbstractEventLoop: +def setup_test_loop(loop_factory=asyncio.new_event_loop): """Create and return an asyncio.BaseEventLoop instance. @@ -515,62 +344,37 @@ def setup_test_loop( once they are done with the loop. """ loop = loop_factory() - try: - module = loop.__class__.__module__ - skip_watcher = 'uvloop' in module - except AttributeError: # pragma: no cover - # Just in case - skip_watcher = True - asyncio.set_event_loop(loop) - if sys.platform != "win32" and not skip_watcher: - policy = asyncio.get_event_loop_policy() - watcher = asyncio.SafeChildWatcher() # type: ignore - watcher.attach_loop(loop) - with contextlib.suppress(NotImplementedError): - policy.set_child_watcher(watcher) + asyncio.set_event_loop(None) return loop -def teardown_test_loop(loop: asyncio.AbstractEventLoop, - fast: bool=False) -> None: +def teardown_test_loop(loop): """Teardown and cleanup an event_loop created by setup_test_loop. + :param loop: the loop to teardown + :type loop: asyncio.BaseEventLoop """ closed = loop.is_closed() if not closed: loop.call_soon(loop.stop) loop.run_forever() loop.close() - - if not fast: - gc.collect() - + gc.collect() asyncio.set_event_loop(None) -def _create_app_mock() -> mock.MagicMock: - def get_dict(app: Any, key: str) -> Any: - return app.__app_dict[key] - - def set_dict(app: Any, key: str, value: Any) -> None: - app.__app_dict[key] = value - - app = mock.MagicMock() - app.__app_dict = {} - app.__getitem__ = get_dict - app.__setitem__ = set_dict - +def _create_app_mock(): + app = mock.Mock() app._debug = False app.on_response_prepare = Signal(app) - app.on_response_prepare.freeze() return app -def _create_transport(sslcontext: Optional[SSLContext]=None) -> mock.Mock: +def _create_transport(sslcontext=None): transport = mock.Mock() - def get_extra_info(key: str) -> Optional[SSLContext]: + def get_extra_info(key): if key == 'sslcontext': return sslcontext else: @@ -580,91 +384,102 @@ def _create_transport(sslcontext: Optional[SSLContext]=None) -> mock.Mock: return transport -def make_mocked_request(method: str, path: str, - headers: Any=None, *, - match_info: Any=sentinel, - version: HttpVersion=HttpVersion(1, 1), - closing: bool=False, - app: Any=None, - writer: Any=sentinel, - protocol: Any=sentinel, - transport: Any=sentinel, - payload: Any=sentinel, - sslcontext: Optional[SSLContext]=None, - client_max_size: int=1024**2, - loop: Any=...) -> Any: +def make_mocked_request(method, path, headers=None, *, + version=HttpVersion(1, 1), closing=False, + app=None, + reader=sentinel, + writer=sentinel, + transport=sentinel, + payload=sentinel, + sslcontext=None, + secure_proxy_ssl_header=None): """Creates mocked web.Request testing purposes. Useful in unit tests, when spinning full web server is overkill or specific conditions and errors are hard to trigger. - """ + :param method: str, that represents HTTP method, like; GET, POST. + :type method: str + + :param path: str, The URL including *PATH INFO* without the host or scheme + :type path: str + + :param headers: mapping containing the headers. Can be anything accepted + by the multidict.CIMultiDict constructor. + :type headers: dict, multidict.CIMultiDict, list of pairs + + :param version: namedtuple with encoded HTTP version + :type version: aiohttp.protocol.HttpVersion + + :param closing: flag indicates that connection should be closed after + response. + :type closing: bool + + :param app: the aiohttp.web application attached for fake request + :type app: aiohttp.web.Application + + :param reader: object for storing and managing incoming data + :type reader: aiohttp.parsers.StreamParser + + :param writer: object for managing outcoming data + :type wirter: aiohttp.parsers.StreamWriter + + :param transport: asyncio transport instance + :type transport: asyncio.transports.Transport - task = mock.Mock() - if loop is ...: - loop = mock.Mock() - loop.create_future.return_value = () + :param payload: raw payload reader object + :type payload: aiohttp.streams.FlowControlStreamReader + + :param sslcontext: ssl.SSLContext object, for HTTPS connection + :type sslcontext: ssl.SSLContext + + :param secure_proxy_ssl_header: A tuple representing a HTTP header/value + combination that signifies a request is secure. + :type secure_proxy_ssl_header: tuple + + """ if version < HttpVersion(1, 1): closing = True if headers: - headers = CIMultiDictProxy(CIMultiDict(headers)) - raw_hdrs = tuple( - (k.encode('utf-8'), v.encode('utf-8')) for k, v in headers.items()) + hdrs = CIMultiDict(headers) + raw_hdrs = [ + (k.encode('utf-8'), v.encode('utf-8')) for k, v in headers.items()] else: - headers = CIMultiDictProxy(CIMultiDict()) - raw_hdrs = () - - chunked = 'chunked' in headers.get(hdrs.TRANSFER_ENCODING, '').lower() + hdrs = CIMultiDict() + raw_hdrs = [] - message = RawRequestMessage( - method, path, version, headers, - raw_hdrs, closing, False, False, chunked, URL(path)) + message = RawRequestMessage(method, path, version, hdrs, + raw_hdrs, closing, False) if app is None: app = _create_app_mock() - if transport is sentinel: - transport = _create_transport(sslcontext) - - if protocol is sentinel: - protocol = mock.Mock() - protocol.transport = transport + if reader is sentinel: + reader = mock.Mock() if writer is sentinel: writer = mock.Mock() - writer.write_headers = make_mocked_coro(None) - writer.write = make_mocked_coro(None) - writer.write_eof = make_mocked_coro(None) - writer.drain = make_mocked_coro(None) - writer.transport = transport - protocol.transport = transport - protocol.writer = writer + if transport is sentinel: + transport = _create_transport(sslcontext) if payload is sentinel: payload = mock.Mock() - req = Request(message, payload, - protocol, writer, task, loop, - client_max_size=client_max_size) - - match_info = UrlMappingMatchInfo( - {} if match_info is sentinel else match_info, mock.Mock()) - match_info.add_app(app) - req._match_info = match_info + req = Request(app, message, payload, + transport, reader, writer, + secure_proxy_ssl_header=secure_proxy_ssl_header) return req -def make_mocked_coro(return_value: Any=sentinel, - raise_exception: Any=sentinel) -> Any: +def make_mocked_coro(return_value=sentinel, raise_exception=sentinel): """Creates a coroutine mock.""" - async def mock_coro(*args: Any, **kwargs: Any) -> Any: + @asyncio.coroutine + def mock_coro(*args, **kwargs): if raise_exception is not sentinel: raise raise_exception - if not inspect.isawaitable(return_value): - return return_value - await return_value + return return_value return mock.Mock(wraps=mock_coro) diff --git a/venv/Lib/site-packages/aiohttp/tracing.py b/venv/Lib/site-packages/aiohttp/tracing.py deleted file mode 100644 index 631e7d00..00000000 --- a/venv/Lib/site-packages/aiohttp/tracing.py +++ /dev/null @@ -1,387 +0,0 @@ -from types import SimpleNamespace -from typing import TYPE_CHECKING, Awaitable, Callable, Type, Union - -import attr -from multidict import CIMultiDict # noqa -from yarl import URL - -from .client_reqrep import ClientResponse -from .signals import Signal - -if TYPE_CHECKING: # pragma: no cover - from .client import ClientSession # noqa - - _SignalArgs = Union[ - 'TraceRequestStartParams', - 'TraceRequestEndParams', - 'TraceRequestExceptionParams', - 'TraceConnectionQueuedStartParams', - 'TraceConnectionQueuedEndParams', - 'TraceConnectionCreateStartParams', - 'TraceConnectionCreateEndParams', - 'TraceConnectionReuseconnParams', - 'TraceDnsResolveHostStartParams', - 'TraceDnsResolveHostEndParams', - 'TraceDnsCacheHitParams', - 'TraceDnsCacheMissParams', - 'TraceRequestRedirectParams', - 'TraceRequestChunkSentParams', - 'TraceResponseChunkReceivedParams', - ] - _Signal = Signal[Callable[[ClientSession, SimpleNamespace, _SignalArgs], - Awaitable[None]]] -else: - _Signal = Signal - - -__all__ = ( - 'TraceConfig', 'TraceRequestStartParams', 'TraceRequestEndParams', - 'TraceRequestExceptionParams', 'TraceConnectionQueuedStartParams', - 'TraceConnectionQueuedEndParams', 'TraceConnectionCreateStartParams', - 'TraceConnectionCreateEndParams', 'TraceConnectionReuseconnParams', - 'TraceDnsResolveHostStartParams', 'TraceDnsResolveHostEndParams', - 'TraceDnsCacheHitParams', 'TraceDnsCacheMissParams', - 'TraceRequestRedirectParams', - 'TraceRequestChunkSentParams', 'TraceResponseChunkReceivedParams', -) - - -class TraceConfig: - """First-class used to trace requests launched via ClientSession - objects.""" - - def __init__( - self, - trace_config_ctx_factory: Type[SimpleNamespace]=SimpleNamespace - ) -> None: - self._on_request_start = Signal(self) # type: _Signal - self._on_request_chunk_sent = Signal(self) # type: _Signal - self._on_response_chunk_received = Signal(self) # type: _Signal - self._on_request_end = Signal(self) # type: _Signal - self._on_request_exception = Signal(self) # type: _Signal - self._on_request_redirect = Signal(self) # type: _Signal - self._on_connection_queued_start = Signal(self) # type: _Signal - self._on_connection_queued_end = Signal(self) # type: _Signal - self._on_connection_create_start = Signal(self) # type: _Signal - self._on_connection_create_end = Signal(self) # type: _Signal - self._on_connection_reuseconn = Signal(self) # type: _Signal - self._on_dns_resolvehost_start = Signal(self) # type: _Signal - self._on_dns_resolvehost_end = Signal(self) # type: _Signal - self._on_dns_cache_hit = Signal(self) # type: _Signal - self._on_dns_cache_miss = Signal(self) # type: _Signal - - self._trace_config_ctx_factory = trace_config_ctx_factory # type: Type[SimpleNamespace] # noqa - - def trace_config_ctx( - self, - trace_request_ctx: SimpleNamespace=None - ) -> SimpleNamespace: # noqa - """ Return a new trace_config_ctx instance """ - return self._trace_config_ctx_factory( - trace_request_ctx=trace_request_ctx) - - def freeze(self) -> None: - self._on_request_start.freeze() - self._on_request_chunk_sent.freeze() - self._on_response_chunk_received.freeze() - self._on_request_end.freeze() - self._on_request_exception.freeze() - self._on_request_redirect.freeze() - self._on_connection_queued_start.freeze() - self._on_connection_queued_end.freeze() - self._on_connection_create_start.freeze() - self._on_connection_create_end.freeze() - self._on_connection_reuseconn.freeze() - self._on_dns_resolvehost_start.freeze() - self._on_dns_resolvehost_end.freeze() - self._on_dns_cache_hit.freeze() - self._on_dns_cache_miss.freeze() - - @property - def on_request_start(self) -> _Signal: - return self._on_request_start - - @property - def on_request_chunk_sent(self) -> _Signal: - return self._on_request_chunk_sent - - @property - def on_response_chunk_received(self) -> _Signal: - return self._on_response_chunk_received - - @property - def on_request_end(self) -> _Signal: - return self._on_request_end - - @property - def on_request_exception(self) -> _Signal: - return self._on_request_exception - - @property - def on_request_redirect(self) -> _Signal: - return self._on_request_redirect - - @property - def on_connection_queued_start(self) -> _Signal: - return self._on_connection_queued_start - - @property - def on_connection_queued_end(self) -> _Signal: - return self._on_connection_queued_end - - @property - def on_connection_create_start(self) -> _Signal: - return self._on_connection_create_start - - @property - def on_connection_create_end(self) -> _Signal: - return self._on_connection_create_end - - @property - def on_connection_reuseconn(self) -> _Signal: - return self._on_connection_reuseconn - - @property - def on_dns_resolvehost_start(self) -> _Signal: - return self._on_dns_resolvehost_start - - @property - def on_dns_resolvehost_end(self) -> _Signal: - return self._on_dns_resolvehost_end - - @property - def on_dns_cache_hit(self) -> _Signal: - return self._on_dns_cache_hit - - @property - def on_dns_cache_miss(self) -> _Signal: - return self._on_dns_cache_miss - - -@attr.s(frozen=True, slots=True) -class TraceRequestStartParams: - """ Parameters sent by the `on_request_start` signal""" - method = attr.ib(type=str) - url = attr.ib(type=URL) - headers = attr.ib(type='CIMultiDict[str]') - - -@attr.s(frozen=True, slots=True) -class TraceRequestChunkSentParams: - """ Parameters sent by the `on_request_chunk_sent` signal""" - chunk = attr.ib(type=bytes) - - -@attr.s(frozen=True, slots=True) -class TraceResponseChunkReceivedParams: - """ Parameters sent by the `on_response_chunk_received` signal""" - chunk = attr.ib(type=bytes) - - -@attr.s(frozen=True, slots=True) -class TraceRequestEndParams: - """ Parameters sent by the `on_request_end` signal""" - method = attr.ib(type=str) - url = attr.ib(type=URL) - headers = attr.ib(type='CIMultiDict[str]') - response = attr.ib(type=ClientResponse) - - -@attr.s(frozen=True, slots=True) -class TraceRequestExceptionParams: - """ Parameters sent by the `on_request_exception` signal""" - method = attr.ib(type=str) - url = attr.ib(type=URL) - headers = attr.ib(type='CIMultiDict[str]') - exception = attr.ib(type=BaseException) - - -@attr.s(frozen=True, slots=True) -class TraceRequestRedirectParams: - """ Parameters sent by the `on_request_redirect` signal""" - method = attr.ib(type=str) - url = attr.ib(type=URL) - headers = attr.ib(type='CIMultiDict[str]') - response = attr.ib(type=ClientResponse) - - -@attr.s(frozen=True, slots=True) -class TraceConnectionQueuedStartParams: - """ Parameters sent by the `on_connection_queued_start` signal""" - - -@attr.s(frozen=True, slots=True) -class TraceConnectionQueuedEndParams: - """ Parameters sent by the `on_connection_queued_end` signal""" - - -@attr.s(frozen=True, slots=True) -class TraceConnectionCreateStartParams: - """ Parameters sent by the `on_connection_create_start` signal""" - - -@attr.s(frozen=True, slots=True) -class TraceConnectionCreateEndParams: - """ Parameters sent by the `on_connection_create_end` signal""" - - -@attr.s(frozen=True, slots=True) -class TraceConnectionReuseconnParams: - """ Parameters sent by the `on_connection_reuseconn` signal""" - - -@attr.s(frozen=True, slots=True) -class TraceDnsResolveHostStartParams: - """ Parameters sent by the `on_dns_resolvehost_start` signal""" - host = attr.ib(type=str) - - -@attr.s(frozen=True, slots=True) -class TraceDnsResolveHostEndParams: - """ Parameters sent by the `on_dns_resolvehost_end` signal""" - host = attr.ib(type=str) - - -@attr.s(frozen=True, slots=True) -class TraceDnsCacheHitParams: - """ Parameters sent by the `on_dns_cache_hit` signal""" - host = attr.ib(type=str) - - -@attr.s(frozen=True, slots=True) -class TraceDnsCacheMissParams: - """ Parameters sent by the `on_dns_cache_miss` signal""" - host = attr.ib(type=str) - - -class Trace: - """ Internal class used to keep together the main dependencies used - at the moment of send a signal.""" - - def __init__(self, - session: 'ClientSession', - trace_config: TraceConfig, - trace_config_ctx: SimpleNamespace) -> None: - self._trace_config = trace_config - self._trace_config_ctx = trace_config_ctx - self._session = session - - async def send_request_start(self, - method: str, - url: URL, - headers: 'CIMultiDict[str]') -> None: - return await self._trace_config.on_request_start.send( - self._session, - self._trace_config_ctx, - TraceRequestStartParams(method, url, headers) - ) - - async def send_request_chunk_sent(self, chunk: bytes) -> None: - return await self._trace_config.on_request_chunk_sent.send( - self._session, - self._trace_config_ctx, - TraceRequestChunkSentParams(chunk) - ) - - async def send_response_chunk_received(self, chunk: bytes) -> None: - return await self._trace_config.on_response_chunk_received.send( - self._session, - self._trace_config_ctx, - TraceResponseChunkReceivedParams(chunk) - ) - - async def send_request_end(self, - method: str, - url: URL, - headers: 'CIMultiDict[str]', - response: ClientResponse) -> None: - return await self._trace_config.on_request_end.send( - self._session, - self._trace_config_ctx, - TraceRequestEndParams(method, url, headers, response) - ) - - async def send_request_exception(self, - method: str, - url: URL, - headers: 'CIMultiDict[str]', - exception: BaseException) -> None: - return await self._trace_config.on_request_exception.send( - self._session, - self._trace_config_ctx, - TraceRequestExceptionParams(method, url, headers, exception) - ) - - async def send_request_redirect(self, - method: str, - url: URL, - headers: 'CIMultiDict[str]', - response: ClientResponse) -> None: - return await self._trace_config._on_request_redirect.send( - self._session, - self._trace_config_ctx, - TraceRequestRedirectParams(method, url, headers, response) - ) - - async def send_connection_queued_start(self) -> None: - return await self._trace_config.on_connection_queued_start.send( - self._session, - self._trace_config_ctx, - TraceConnectionQueuedStartParams() - ) - - async def send_connection_queued_end(self) -> None: - return await self._trace_config.on_connection_queued_end.send( - self._session, - self._trace_config_ctx, - TraceConnectionQueuedEndParams() - ) - - async def send_connection_create_start(self) -> None: - return await self._trace_config.on_connection_create_start.send( - self._session, - self._trace_config_ctx, - TraceConnectionCreateStartParams() - ) - - async def send_connection_create_end(self) -> None: - return await self._trace_config.on_connection_create_end.send( - self._session, - self._trace_config_ctx, - TraceConnectionCreateEndParams() - ) - - async def send_connection_reuseconn(self) -> None: - return await self._trace_config.on_connection_reuseconn.send( - self._session, - self._trace_config_ctx, - TraceConnectionReuseconnParams() - ) - - async def send_dns_resolvehost_start(self, host: str) -> None: - return await self._trace_config.on_dns_resolvehost_start.send( - self._session, - self._trace_config_ctx, - TraceDnsResolveHostStartParams(host) - ) - - async def send_dns_resolvehost_end(self, host: str) -> None: - return await self._trace_config.on_dns_resolvehost_end.send( - self._session, - self._trace_config_ctx, - TraceDnsResolveHostEndParams(host) - ) - - async def send_dns_cache_hit(self, host: str) -> None: - return await self._trace_config.on_dns_cache_hit.send( - self._session, - self._trace_config_ctx, - TraceDnsCacheHitParams(host) - ) - - async def send_dns_cache_miss(self, host: str) -> None: - return await self._trace_config.on_dns_cache_miss.send( - self._session, - self._trace_config_ctx, - TraceDnsCacheMissParams(host) - ) diff --git a/venv/Lib/site-packages/aiohttp/typedefs.py b/venv/Lib/site-packages/aiohttp/typedefs.py deleted file mode 100644 index 3c42f6ab..00000000 --- a/venv/Lib/site-packages/aiohttp/typedefs.py +++ /dev/null @@ -1,53 +0,0 @@ -import json -import os # noqa -import pathlib # noqa -import sys -from typing import ( - TYPE_CHECKING, - Any, - Callable, - Iterable, - Mapping, - Tuple, - Union, -) - -from multidict import ( - CIMultiDict, - CIMultiDictProxy, - MultiDict, - MultiDictProxy, - istr, -) -from yarl import URL - -DEFAULT_JSON_ENCODER = json.dumps -DEFAULT_JSON_DECODER = json.loads - -if TYPE_CHECKING: # pragma: no cover - _CIMultiDict = CIMultiDict[str] - _CIMultiDictProxy = CIMultiDictProxy[str] - _MultiDict = MultiDict[str] - _MultiDictProxy = MultiDictProxy[str] - from http.cookies import BaseCookie # noqa -else: - _CIMultiDict = CIMultiDict - _CIMultiDictProxy = CIMultiDictProxy - _MultiDict = MultiDict - _MultiDictProxy = MultiDictProxy - -Byteish = Union[bytes, bytearray, memoryview] -JSONEncoder = Callable[[Any], str] -JSONDecoder = Callable[[str], Any] -LooseHeaders = Union[Mapping[Union[str, istr], str], _CIMultiDict, - _CIMultiDictProxy] -RawHeaders = Tuple[Tuple[bytes, bytes], ...] -StrOrURL = Union[str, URL] -LooseCookies = Union[Iterable[Tuple[str, 'BaseCookie[str]']], - Mapping[str, 'BaseCookie[str]'], 'BaseCookie[str]'] - - -if sys.version_info >= (3, 6): - PathLike = Union[str, 'os.PathLike[str]'] -else: - PathLike = Union[str, pathlib.PurePath] diff --git a/venv/Lib/site-packages/aiohttp/web.py b/venv/Lib/site-packages/aiohttp/web.py index 12fd09aa..f06535c6 100644 --- a/venv/Lib/site-packages/aiohttp/web.py +++ b/venv/Lib/site-packages/aiohttp/web.py @@ -1,446 +1,333 @@ import asyncio -import logging -import socket import sys +import warnings from argparse import ArgumentParser -from collections.abc import Iterable from importlib import import_module -from typing import Any, Awaitable, Callable, List, Optional, Type, Union, cast - -from .abc import AbstractAccessLogger -from .helpers import all_tasks -from .log import access_logger -from .web_app import Application as Application -from .web_app import CleanupError as CleanupError -from .web_exceptions import HTTPAccepted as HTTPAccepted -from .web_exceptions import HTTPBadGateway as HTTPBadGateway -from .web_exceptions import HTTPBadRequest as HTTPBadRequest -from .web_exceptions import HTTPClientError as HTTPClientError -from .web_exceptions import HTTPConflict as HTTPConflict -from .web_exceptions import HTTPCreated as HTTPCreated -from .web_exceptions import HTTPError as HTTPError -from .web_exceptions import HTTPException as HTTPException -from .web_exceptions import HTTPExpectationFailed as HTTPExpectationFailed -from .web_exceptions import HTTPFailedDependency as HTTPFailedDependency -from .web_exceptions import HTTPForbidden as HTTPForbidden -from .web_exceptions import HTTPFound as HTTPFound -from .web_exceptions import HTTPGatewayTimeout as HTTPGatewayTimeout -from .web_exceptions import HTTPGone as HTTPGone -from .web_exceptions import HTTPInsufficientStorage as HTTPInsufficientStorage -from .web_exceptions import HTTPInternalServerError as HTTPInternalServerError -from .web_exceptions import HTTPLengthRequired as HTTPLengthRequired -from .web_exceptions import HTTPMethodNotAllowed as HTTPMethodNotAllowed -from .web_exceptions import HTTPMisdirectedRequest as HTTPMisdirectedRequest -from .web_exceptions import HTTPMovedPermanently as HTTPMovedPermanently -from .web_exceptions import HTTPMultipleChoices as HTTPMultipleChoices -from .web_exceptions import ( - HTTPNetworkAuthenticationRequired as HTTPNetworkAuthenticationRequired, -) -from .web_exceptions import HTTPNoContent as HTTPNoContent -from .web_exceptions import ( - HTTPNonAuthoritativeInformation as HTTPNonAuthoritativeInformation, -) -from .web_exceptions import HTTPNotAcceptable as HTTPNotAcceptable -from .web_exceptions import HTTPNotExtended as HTTPNotExtended -from .web_exceptions import HTTPNotFound as HTTPNotFound -from .web_exceptions import HTTPNotImplemented as HTTPNotImplemented -from .web_exceptions import HTTPNotModified as HTTPNotModified -from .web_exceptions import HTTPOk as HTTPOk -from .web_exceptions import HTTPPartialContent as HTTPPartialContent -from .web_exceptions import HTTPPaymentRequired as HTTPPaymentRequired -from .web_exceptions import HTTPPermanentRedirect as HTTPPermanentRedirect -from .web_exceptions import HTTPPreconditionFailed as HTTPPreconditionFailed -from .web_exceptions import ( - HTTPPreconditionRequired as HTTPPreconditionRequired, -) -from .web_exceptions import ( - HTTPProxyAuthenticationRequired as HTTPProxyAuthenticationRequired, -) -from .web_exceptions import HTTPRedirection as HTTPRedirection -from .web_exceptions import ( - HTTPRequestEntityTooLarge as HTTPRequestEntityTooLarge, -) -from .web_exceptions import ( - HTTPRequestHeaderFieldsTooLarge as HTTPRequestHeaderFieldsTooLarge, -) -from .web_exceptions import ( - HTTPRequestRangeNotSatisfiable as HTTPRequestRangeNotSatisfiable, -) -from .web_exceptions import HTTPRequestTimeout as HTTPRequestTimeout -from .web_exceptions import HTTPRequestURITooLong as HTTPRequestURITooLong -from .web_exceptions import HTTPResetContent as HTTPResetContent -from .web_exceptions import HTTPSeeOther as HTTPSeeOther -from .web_exceptions import HTTPServerError as HTTPServerError -from .web_exceptions import HTTPServiceUnavailable as HTTPServiceUnavailable -from .web_exceptions import HTTPSuccessful as HTTPSuccessful -from .web_exceptions import HTTPTemporaryRedirect as HTTPTemporaryRedirect -from .web_exceptions import HTTPTooManyRequests as HTTPTooManyRequests -from .web_exceptions import HTTPUnauthorized as HTTPUnauthorized -from .web_exceptions import ( - HTTPUnavailableForLegalReasons as HTTPUnavailableForLegalReasons, -) -from .web_exceptions import HTTPUnprocessableEntity as HTTPUnprocessableEntity -from .web_exceptions import ( - HTTPUnsupportedMediaType as HTTPUnsupportedMediaType, -) -from .web_exceptions import HTTPUpgradeRequired as HTTPUpgradeRequired -from .web_exceptions import HTTPUseProxy as HTTPUseProxy -from .web_exceptions import ( - HTTPVariantAlsoNegotiates as HTTPVariantAlsoNegotiates, -) -from .web_exceptions import HTTPVersionNotSupported as HTTPVersionNotSupported -from .web_fileresponse import FileResponse as FileResponse -from .web_log import AccessLogger -from .web_middlewares import middleware as middleware -from .web_middlewares import ( - normalize_path_middleware as normalize_path_middleware, -) -from .web_protocol import PayloadAccessError as PayloadAccessError -from .web_protocol import RequestHandler as RequestHandler -from .web_protocol import RequestPayloadError as RequestPayloadError -from .web_request import BaseRequest as BaseRequest -from .web_request import FileField as FileField -from .web_request import Request as Request -from .web_response import ContentCoding as ContentCoding -from .web_response import Response as Response -from .web_response import StreamResponse as StreamResponse -from .web_response import json_response as json_response -from .web_routedef import AbstractRouteDef as AbstractRouteDef -from .web_routedef import RouteDef as RouteDef -from .web_routedef import RouteTableDef as RouteTableDef -from .web_routedef import StaticDef as StaticDef -from .web_routedef import delete as delete -from .web_routedef import get as get -from .web_routedef import head as head -from .web_routedef import options as options -from .web_routedef import patch as patch -from .web_routedef import post as post -from .web_routedef import put as put -from .web_routedef import route as route -from .web_routedef import static as static -from .web_routedef import view as view -from .web_runner import AppRunner as AppRunner -from .web_runner import BaseRunner as BaseRunner -from .web_runner import BaseSite as BaseSite -from .web_runner import GracefulExit as GracefulExit -from .web_runner import NamedPipeSite as NamedPipeSite -from .web_runner import ServerRunner as ServerRunner -from .web_runner import SockSite as SockSite -from .web_runner import TCPSite as TCPSite -from .web_runner import UnixSite as UnixSite -from .web_server import Server as Server -from .web_urldispatcher import AbstractResource as AbstractResource -from .web_urldispatcher import AbstractRoute as AbstractRoute -from .web_urldispatcher import DynamicResource as DynamicResource -from .web_urldispatcher import PlainResource as PlainResource -from .web_urldispatcher import Resource as Resource -from .web_urldispatcher import ResourceRoute as ResourceRoute -from .web_urldispatcher import StaticResource as StaticResource -from .web_urldispatcher import UrlDispatcher as UrlDispatcher -from .web_urldispatcher import UrlMappingMatchInfo as UrlMappingMatchInfo -from .web_urldispatcher import View as View -from .web_ws import WebSocketReady as WebSocketReady -from .web_ws import WebSocketResponse as WebSocketResponse -from .web_ws import WSMsgType as WSMsgType - -__all__ = ( - # web_app - 'Application', - 'CleanupError', - # web_exceptions - 'HTTPAccepted', - 'HTTPBadGateway', - 'HTTPBadRequest', - 'HTTPClientError', - 'HTTPConflict', - 'HTTPCreated', - 'HTTPError', - 'HTTPException', - 'HTTPExpectationFailed', - 'HTTPFailedDependency', - 'HTTPForbidden', - 'HTTPFound', - 'HTTPGatewayTimeout', - 'HTTPGone', - 'HTTPInsufficientStorage', - 'HTTPInternalServerError', - 'HTTPLengthRequired', - 'HTTPMethodNotAllowed', - 'HTTPMisdirectedRequest', - 'HTTPMovedPermanently', - 'HTTPMultipleChoices', - 'HTTPNetworkAuthenticationRequired', - 'HTTPNoContent', - 'HTTPNonAuthoritativeInformation', - 'HTTPNotAcceptable', - 'HTTPNotExtended', - 'HTTPNotFound', - 'HTTPNotImplemented', - 'HTTPNotModified', - 'HTTPOk', - 'HTTPPartialContent', - 'HTTPPaymentRequired', - 'HTTPPermanentRedirect', - 'HTTPPreconditionFailed', - 'HTTPPreconditionRequired', - 'HTTPProxyAuthenticationRequired', - 'HTTPRedirection', - 'HTTPRequestEntityTooLarge', - 'HTTPRequestHeaderFieldsTooLarge', - 'HTTPRequestRangeNotSatisfiable', - 'HTTPRequestTimeout', - 'HTTPRequestURITooLong', - 'HTTPResetContent', - 'HTTPSeeOther', - 'HTTPServerError', - 'HTTPServiceUnavailable', - 'HTTPSuccessful', - 'HTTPTemporaryRedirect', - 'HTTPTooManyRequests', - 'HTTPUnauthorized', - 'HTTPUnavailableForLegalReasons', - 'HTTPUnprocessableEntity', - 'HTTPUnsupportedMediaType', - 'HTTPUpgradeRequired', - 'HTTPUseProxy', - 'HTTPVariantAlsoNegotiates', - 'HTTPVersionNotSupported', - # web_fileresponse - 'FileResponse', - # web_middlewares - 'middleware', - 'normalize_path_middleware', - # web_protocol - 'PayloadAccessError', - 'RequestHandler', - 'RequestPayloadError', - # web_request - 'BaseRequest', - 'FileField', - 'Request', - # web_response - 'ContentCoding', - 'Response', - 'StreamResponse', - 'json_response', - # web_routedef - 'AbstractRouteDef', - 'RouteDef', - 'RouteTableDef', - 'StaticDef', - 'delete', - 'get', - 'head', - 'options', - 'patch', - 'post', - 'put', - 'route', - 'static', - 'view', - # web_runner - 'AppRunner', - 'BaseRunner', - 'BaseSite', - 'GracefulExit', - 'ServerRunner', - 'SockSite', - 'TCPSite', - 'UnixSite', - 'NamedPipeSite', - # web_server - 'Server', - # web_urldispatcher - 'AbstractResource', - 'AbstractRoute', - 'DynamicResource', - 'PlainResource', - 'Resource', - 'ResourceRoute', - 'StaticResource', - 'UrlDispatcher', - 'UrlMappingMatchInfo', - 'View', - # web_ws - 'WebSocketReady', - 'WebSocketResponse', - 'WSMsgType', - # web - 'run_app', -) - - -try: - from ssl import SSLContext -except ImportError: # pragma: no cover - SSLContext = Any # type: ignore - - -async def _run_app(app: Union[Application, Awaitable[Application]], *, - host: Optional[str]=None, - port: Optional[int]=None, - path: Optional[str]=None, - sock: Optional[socket.socket]=None, - shutdown_timeout: float=60.0, - ssl_context: Optional[SSLContext]=None, - print: Callable[..., None]=print, - backlog: int=128, - access_log_class: Type[AbstractAccessLogger]=AccessLogger, - access_log_format: str=AccessLogger.LOG_FORMAT, - access_log: Optional[logging.Logger]=access_logger, - handle_signals: bool=True, - reuse_address: Optional[bool]=None, - reuse_port: Optional[bool]=None) -> None: - # A internal functio to actually do all dirty job for application running - if asyncio.iscoroutine(app): - app = await app # type: ignore - - app = cast(Application, app) - - runner = AppRunner(app, handle_signals=handle_signals, - access_log_class=access_log_class, - access_log_format=access_log_format, - access_log=access_log) - - await runner.setup() - - sites = [] # type: List[BaseSite] - try: - if host is not None: - if isinstance(host, (str, bytes, bytearray, memoryview)): - sites.append(TCPSite(runner, host, port, - shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, - backlog=backlog, - reuse_address=reuse_address, - reuse_port=reuse_port)) - else: - for h in host: - sites.append(TCPSite(runner, h, port, - shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, - backlog=backlog, - reuse_address=reuse_address, - reuse_port=reuse_port)) - elif path is None and sock is None or port is not None: - sites.append(TCPSite(runner, port=port, - shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, backlog=backlog, - reuse_address=reuse_address, - reuse_port=reuse_port)) - - if path is not None: - if isinstance(path, (str, bytes, bytearray, memoryview)): - sites.append(UnixSite(runner, path, - shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, - backlog=backlog)) - else: - for p in path: - sites.append(UnixSite(runner, p, - shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, - backlog=backlog)) - - if sock is not None: - if not isinstance(sock, Iterable): - sites.append(SockSite(runner, sock, - shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, - backlog=backlog)) - else: - for s in sock: - sites.append(SockSite(runner, s, - shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, - backlog=backlog)) - for site in sites: - await site.start() - - if print: # pragma: no branch - names = sorted(str(s.name) for s in runner.sites) - print("======== Running on {} ========\n" - "(Press CTRL+C to quit)".format(', '.join(names))) - while True: - await asyncio.sleep(3600) # sleep forever by 1 hour intervals - finally: - await runner.cleanup() - - -def _cancel_all_tasks(loop: asyncio.AbstractEventLoop) -> None: - to_cancel = all_tasks(loop) - if not to_cancel: - return - - for task in to_cancel: - task.cancel() - - loop.run_until_complete( - asyncio.gather(*to_cancel, loop=loop, return_exceptions=True)) - - for task in to_cancel: - if task.cancelled(): - continue - if task.exception() is not None: - loop.call_exception_handler({ - 'message': 'unhandled exception during asyncio.run() shutdown', - 'exception': task.exception(), - 'task': task, - }) - - -def run_app(app: Union[Application, Awaitable[Application]], *, - host: Optional[str]=None, - port: Optional[int]=None, - path: Optional[str]=None, - sock: Optional[socket.socket]=None, - shutdown_timeout: float=60.0, - ssl_context: Optional[SSLContext]=None, - print: Callable[..., None]=print, - backlog: int=128, - access_log_class: Type[AbstractAccessLogger]=AccessLogger, - access_log_format: str=AccessLogger.LOG_FORMAT, - access_log: Optional[logging.Logger]=access_logger, - handle_signals: bool=True, - reuse_address: Optional[bool]=None, - reuse_port: Optional[bool]=None) -> None: +from . import hdrs, web_exceptions, web_reqrep, web_urldispatcher, web_ws +from .abc import AbstractMatchInfo, AbstractRouter +from .helpers import sentinel +from .log import web_logger +from .protocol import HttpVersion # noqa +from .server import ServerHttpProtocol +from .signals import PostSignal, PreSignal, Signal +from .web_exceptions import * # noqa +from .web_reqrep import * # noqa +from .web_urldispatcher import * # noqa +from .web_ws import * # noqa + + +__all__ = (web_reqrep.__all__ + + web_exceptions.__all__ + + web_urldispatcher.__all__ + + web_ws.__all__ + + ('Application', 'RequestHandler', + 'RequestHandlerFactory', 'HttpVersion', + 'MsgType')) + + +class RequestHandler(ServerHttpProtocol): + + _meth = 'none' + _path = 'none' + + def __init__(self, manager, app, router, *, + secure_proxy_ssl_header=None, **kwargs): + super().__init__(**kwargs) + + self._manager = manager + self._app = app + self._router = router + self._middlewares = app.middlewares + self._secure_proxy_ssl_header = secure_proxy_ssl_header + + def __repr__(self): + return "<{} {}:{} {}>".format( + self.__class__.__name__, self._meth, self._path, + 'connected' if self.transport is not None else 'disconnected') + + def connection_made(self, transport): + super().connection_made(transport) + + self._manager.connection_made(self, transport) + + def connection_lost(self, exc): + self._manager.connection_lost(self, exc) + + super().connection_lost(exc) + + @asyncio.coroutine + def handle_request(self, message, payload): + self._manager._requests_count += 1 + if self.access_log: + now = self._loop.time() + + app = self._app + request = web_reqrep.Request( + app, message, payload, + self.transport, self.reader, self.writer, + secure_proxy_ssl_header=self._secure_proxy_ssl_header) + self._meth = request.method + self._path = request.path + try: + match_info = yield from self._router.resolve(request) + + assert isinstance(match_info, AbstractMatchInfo), match_info + + resp = None + request._match_info = match_info + expect = request.headers.get(hdrs.EXPECT) + if expect: + resp = ( + yield from match_info.expect_handler(request)) + + if resp is None: + handler = match_info.handler + for factory in reversed(self._middlewares): + handler = yield from factory(app, handler) + resp = yield from handler(request) + + assert isinstance(resp, web_reqrep.StreamResponse), \ + ("Handler {!r} should return response instance, " + "got {!r} [middlewares {!r}]").format( + match_info.handler, type(resp), self._middlewares) + except web_exceptions.HTTPException as exc: + resp = exc + + resp_msg = yield from resp.prepare(request) + yield from resp.write_eof() + + # notify server about keep-alive + self.keep_alive(resp.keep_alive) + + # log access + if self.access_log: + self.log_access(message, None, resp_msg, self._loop.time() - now) + + # for repr + self._meth = 'none' + self._path = 'none' + + +class RequestHandlerFactory: + + def __init__(self, app, router, *, + handler=RequestHandler, loop=None, + secure_proxy_ssl_header=None, **kwargs): + self._app = app + self._router = router + self._handler = handler + self._loop = loop + self._connections = {} + self._secure_proxy_ssl_header = secure_proxy_ssl_header + self._kwargs = kwargs + self._kwargs.setdefault('logger', app.logger) + self._requests_count = 0 + + @property + def requests_count(self): + """Number of processed requests.""" + return self._requests_count + + @property + def secure_proxy_ssl_header(self): + return self._secure_proxy_ssl_header + + @property + def connections(self): + return list(self._connections.keys()) + + def connection_made(self, handler, transport): + self._connections[handler] = transport + + def connection_lost(self, handler, exc=None): + if handler in self._connections: + del self._connections[handler] + + @asyncio.coroutine + def finish_connections(self, timeout=None): + coros = [conn.shutdown(timeout) for conn in self._connections] + yield from asyncio.gather(*coros, loop=self._loop) + self._connections.clear() + + def __call__(self): + return self._handler( + self, self._app, self._router, loop=self._loop, + secure_proxy_ssl_header=self._secure_proxy_ssl_header, + **self._kwargs) + + +class Application(dict): + + def __init__(self, *, logger=web_logger, loop=None, + router=None, handler_factory=RequestHandlerFactory, + middlewares=(), debug=False): + if loop is None: + loop = asyncio.get_event_loop() + if router is None: + router = web_urldispatcher.UrlDispatcher() + assert isinstance(router, AbstractRouter), router + + self._debug = debug + self._router = router + self._handler_factory = handler_factory + self._loop = loop + self.logger = logger + + self._middlewares = list(middlewares) + + self._on_pre_signal = PreSignal() + self._on_post_signal = PostSignal() + self._on_response_prepare = Signal(self) + self._on_startup = Signal(self) + self._on_shutdown = Signal(self) + self._on_cleanup = Signal(self) + + @property + def debug(self): + return self._debug + + @property + def on_response_prepare(self): + return self._on_response_prepare + + @property + def on_pre_signal(self): + return self._on_pre_signal + + @property + def on_post_signal(self): + return self._on_post_signal + + @property + def on_startup(self): + return self._on_startup + + @property + def on_shutdown(self): + return self._on_shutdown + + @property + def on_cleanup(self): + return self._on_cleanup + + @property + def router(self): + return self._router + + @property + def loop(self): + return self._loop + + @property + def middlewares(self): + return self._middlewares + + def make_handler(self, **kwargs): + debug = kwargs.pop('debug', sentinel) + if debug is not sentinel: + warnings.warn( + "`debug` parameter is deprecated. " + "Use Application's debug mode instead", DeprecationWarning) + if debug != self.debug: + raise ValueError( + "The value of `debug` parameter conflicts with the debug " + "settings of the `Application` instance. The " + "application's debug mode setting should be used instead " + "as a single point to setup a debug mode. For more " + "information please check " + "http://aiohttp.readthedocs.io/en/stable/" + "web_reference.html#aiohttp.web.Application" + ) + return self._handler_factory(self, self.router, debug=self.debug, + loop=self.loop, **kwargs) + + @asyncio.coroutine + def startup(self): + """Causes on_startup signal + + Should be called in the event loop along with the request handler. + """ + yield from self.on_startup.send(self) + + @asyncio.coroutine + def shutdown(self): + """Causes on_shutdown signal + + Should be called before cleanup() + """ + yield from self.on_shutdown.send(self) + + @asyncio.coroutine + def cleanup(self): + """Causes on_cleanup signal + + Should be called after shutdown() + """ + yield from self.on_cleanup.send(self) + + @asyncio.coroutine + def finish(self): + """Finalize an application. + + Deprecated alias for .cleanup() + """ + warnings.warn("Use .cleanup() instead", DeprecationWarning) + yield from self.cleanup() + + def register_on_finish(self, func, *args, **kwargs): + warnings.warn("Use .on_cleanup.append() instead", DeprecationWarning) + self.on_cleanup.append(lambda app: func(app, *args, **kwargs)) + + def copy(self): + raise NotImplementedError + + def __call__(self): + """gunicorn compatibility""" + return self + + def __repr__(self): + return "" + + +def run_app(app, *, host='0.0.0.0', port=None, + shutdown_timeout=60.0, ssl_context=None, + print=print, backlog=128): """Run an app locally""" - loop = asyncio.get_event_loop() + if port is None: + if not ssl_context: + port = 8080 + else: + port = 8443 + + loop = app.loop - # Configure if and only if in debugging mode and using the default logger - if loop.get_debug() and access_log and access_log.name == 'aiohttp.access': - if access_log.level == logging.NOTSET: - access_log.setLevel(logging.DEBUG) - if not access_log.hasHandlers(): - access_log.addHandler(logging.StreamHandler()) + handler = app.make_handler() + server = loop.create_server(handler, host, port, ssl=ssl_context, + backlog=backlog) + srv, startup_res = loop.run_until_complete(asyncio.gather(server, + app.startup(), + loop=loop)) + + scheme = 'https' if ssl_context else 'http' + print("======== Running on {scheme}://{host}:{port}/ ========\n" + "(Press CTRL+C to quit)".format( + scheme=scheme, host=host, port=port)) try: - loop.run_until_complete(_run_app(app, - host=host, - port=port, - path=path, - sock=sock, - shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, - print=print, - backlog=backlog, - access_log_class=access_log_class, - access_log_format=access_log_format, - access_log=access_log, - handle_signals=handle_signals, - reuse_address=reuse_address, - reuse_port=reuse_port)) - except (GracefulExit, KeyboardInterrupt): # pragma: no cover + loop.run_forever() + except KeyboardInterrupt: # pragma: no cover pass finally: - _cancel_all_tasks(loop) - if sys.version_info >= (3, 6): # don't use PY_36 to pass mypy - loop.run_until_complete(loop.shutdown_asyncgens()) - loop.close() + srv.close() + loop.run_until_complete(srv.wait_closed()) + loop.run_until_complete(app.shutdown()) + loop.run_until_complete(handler.finish_connections(shutdown_timeout)) + loop.run_until_complete(app.cleanup()) + loop.close() -def main(argv: List[str]) -> None: +def main(argv): arg_parser = ArgumentParser( description="aiohttp.web Application server", prog="aiohttp.web" @@ -462,11 +349,6 @@ def main(argv: List[str]) -> None: type=int, default="8080" ) - arg_parser.add_argument( - "-U", "--path", - help="Unix file system path to serve on. Specifying a path will cause " - "hostname and port arguments to be ignored.", - ) args, extra_argv = arg_parser.parse_known_args(argv) # Import logic @@ -479,24 +361,16 @@ def main(argv: List[str]) -> None: arg_parser.error("relative module names not supported") try: module = import_module(mod_str) - except ImportError as ex: - arg_parser.error("unable to import %s: %s" % (mod_str, ex)) + except ImportError: + arg_parser.error("module %r not found" % mod_str) try: func = getattr(module, func_str) except AttributeError: arg_parser.error("module %r has no attribute %r" % (mod_str, func_str)) - # Compatibility logic - if args.path is not None and not hasattr(socket, 'AF_UNIX'): - arg_parser.error("file system paths not supported by your operating" - " environment") - - logging.basicConfig(level=logging.DEBUG) - app = func(extra_argv) - run_app(app, host=args.hostname, port=args.port, path=args.path) + run_app(app, host=args.hostname, port=args.port) arg_parser.exit(message="Stopped\n") - if __name__ == "__main__": # pragma: no branch main(sys.argv[1:]) # pragma: no cover diff --git a/venv/Lib/site-packages/aiohttp/web_app.py b/venv/Lib/site-packages/aiohttp/web_app.py deleted file mode 100644 index 783bdbe9..00000000 --- a/venv/Lib/site-packages/aiohttp/web_app.py +++ /dev/null @@ -1,514 +0,0 @@ -import asyncio -import logging -import warnings -from functools import partial -from typing import ( # noqa - TYPE_CHECKING, - Any, - AsyncIterator, - Awaitable, - Callable, - Dict, - Iterable, - Iterator, - List, - Mapping, - MutableMapping, - Optional, - Sequence, - Tuple, - Type, - Union, - cast, -) - -from . import hdrs -from .abc import ( - AbstractAccessLogger, - AbstractMatchInfo, - AbstractRouter, - AbstractStreamWriter, -) -from .frozenlist import FrozenList -from .helpers import DEBUG -from .http_parser import RawRequestMessage -from .log import web_logger -from .signals import Signal -from .streams import StreamReader -from .web_log import AccessLogger -from .web_middlewares import _fix_request_current_app -from .web_protocol import RequestHandler -from .web_request import Request -from .web_response import StreamResponse -from .web_routedef import AbstractRouteDef -from .web_server import Server -from .web_urldispatcher import ( - AbstractResource, - Domain, - MaskDomain, - MatchedSubAppResource, - PrefixedSubAppResource, - UrlDispatcher, -) - -__all__ = ('Application', 'CleanupError') - - -if TYPE_CHECKING: # pragma: no cover - _AppSignal = Signal[Callable[['Application'], Awaitable[None]]] - _RespPrepareSignal = Signal[Callable[[Request, StreamResponse], - Awaitable[None]]] - _Handler = Callable[[Request], Awaitable[StreamResponse]] - _Middleware = Union[Callable[[Request, _Handler], - Awaitable[StreamResponse]], - Callable[['Application', _Handler], # old-style - Awaitable[_Handler]]] - _Middlewares = FrozenList[_Middleware] - _MiddlewaresHandlers = Optional[Sequence[Tuple[_Middleware, bool]]] - _Subapps = List['Application'] -else: - # No type checker mode, skip types - _AppSignal = Signal - _RespPrepareSignal = Signal - _Handler = Callable - _Middleware = Callable - _Middlewares = FrozenList - _MiddlewaresHandlers = Optional[Sequence] - _Subapps = List - - -class Application(MutableMapping[str, Any]): - ATTRS = frozenset([ - 'logger', '_debug', '_router', '_loop', '_handler_args', - '_middlewares', '_middlewares_handlers', '_run_middlewares', - '_state', '_frozen', '_pre_frozen', '_subapps', - '_on_response_prepare', '_on_startup', '_on_shutdown', - '_on_cleanup', '_client_max_size', '_cleanup_ctx']) - - def __init__(self, *, - logger: logging.Logger=web_logger, - router: Optional[UrlDispatcher]=None, - middlewares: Iterable[_Middleware]=(), - handler_args: Mapping[str, Any]=None, - client_max_size: int=1024**2, - loop: Optional[asyncio.AbstractEventLoop]=None, - debug: Any=... # mypy doesn't support ellipsis - ) -> None: - if router is None: - router = UrlDispatcher() - else: - warnings.warn("router argument is deprecated", DeprecationWarning, - stacklevel=2) - assert isinstance(router, AbstractRouter), router - - if loop is not None: - warnings.warn("loop argument is deprecated", DeprecationWarning, - stacklevel=2) - - if debug is not ...: - warnings.warn("debug argument is deprecated", - DeprecationWarning, - stacklevel=2) - self._debug = debug - self._router = router # type: UrlDispatcher - self._loop = loop - self._handler_args = handler_args - self.logger = logger - - self._middlewares = FrozenList(middlewares) # type: _Middlewares - - # initialized on freezing - self._middlewares_handlers = None # type: _MiddlewaresHandlers - # initialized on freezing - self._run_middlewares = None # type: Optional[bool] - - self._state = {} # type: Dict[str, Any] - self._frozen = False - self._pre_frozen = False - self._subapps = [] # type: _Subapps - - self._on_response_prepare = Signal(self) # type: _RespPrepareSignal - self._on_startup = Signal(self) # type: _AppSignal - self._on_shutdown = Signal(self) # type: _AppSignal - self._on_cleanup = Signal(self) # type: _AppSignal - self._cleanup_ctx = CleanupContext() - self._on_startup.append(self._cleanup_ctx._on_startup) - self._on_cleanup.append(self._cleanup_ctx._on_cleanup) - self._client_max_size = client_max_size - - def __init_subclass__(cls: Type['Application']) -> None: - warnings.warn("Inheritance class {} from web.Application " - "is discouraged".format(cls.__name__), - DeprecationWarning, - stacklevel=2) - - if DEBUG: # pragma: no cover - def __setattr__(self, name: str, val: Any) -> None: - if name not in self.ATTRS: - warnings.warn("Setting custom web.Application.{} attribute " - "is discouraged".format(name), - DeprecationWarning, - stacklevel=2) - super().__setattr__(name, val) - - # MutableMapping API - - def __eq__(self, other: object) -> bool: - return self is other - - def __getitem__(self, key: str) -> Any: - return self._state[key] - - def _check_frozen(self) -> None: - if self._frozen: - warnings.warn("Changing state of started or joined " - "application is deprecated", - DeprecationWarning, - stacklevel=3) - - def __setitem__(self, key: str, value: Any) -> None: - self._check_frozen() - self._state[key] = value - - def __delitem__(self, key: str) -> None: - self._check_frozen() - del self._state[key] - - def __len__(self) -> int: - return len(self._state) - - def __iter__(self) -> Iterator[str]: - return iter(self._state) - - ######## - @property - def loop(self) -> asyncio.AbstractEventLoop: - # Technically the loop can be None - # but we mask it by explicit type cast - # to provide more convinient type annotation - warnings.warn("loop property is deprecated", - DeprecationWarning, - stacklevel=2) - return cast(asyncio.AbstractEventLoop, self._loop) - - def _set_loop(self, loop: Optional[asyncio.AbstractEventLoop]) -> None: - if loop is None: - loop = asyncio.get_event_loop() - if self._loop is not None and self._loop is not loop: - raise RuntimeError( - "web.Application instance initialized with different loop") - - self._loop = loop - - # set loop debug - if self._debug is ...: - self._debug = loop.get_debug() - - # set loop to sub applications - for subapp in self._subapps: - subapp._set_loop(loop) - - @property - def pre_frozen(self) -> bool: - return self._pre_frozen - - def pre_freeze(self) -> None: - if self._pre_frozen: - return - - self._pre_frozen = True - self._middlewares.freeze() - self._router.freeze() - self._on_response_prepare.freeze() - self._cleanup_ctx.freeze() - self._on_startup.freeze() - self._on_shutdown.freeze() - self._on_cleanup.freeze() - self._middlewares_handlers = tuple(self._prepare_middleware()) - - # If current app and any subapp do not have middlewares avoid run all - # of the code footprint that it implies, which have a middleware - # hardcoded per app that sets up the current_app attribute. If no - # middlewares are configured the handler will receive the proper - # current_app without needing all of this code. - self._run_middlewares = True if self.middlewares else False - - for subapp in self._subapps: - subapp.pre_freeze() - self._run_middlewares = (self._run_middlewares or - subapp._run_middlewares) - - @property - def frozen(self) -> bool: - return self._frozen - - def freeze(self) -> None: - if self._frozen: - return - - self.pre_freeze() - self._frozen = True - for subapp in self._subapps: - subapp.freeze() - - @property - def debug(self) -> bool: - warnings.warn("debug property is deprecated", - DeprecationWarning, - stacklevel=2) - return self._debug - - def _reg_subapp_signals(self, subapp: 'Application') -> None: - - def reg_handler(signame: str) -> None: - subsig = getattr(subapp, signame) - - async def handler(app: 'Application') -> None: - await subsig.send(subapp) - appsig = getattr(self, signame) - appsig.append(handler) - - reg_handler('on_startup') - reg_handler('on_shutdown') - reg_handler('on_cleanup') - - def add_subapp(self, prefix: str, - subapp: 'Application') -> AbstractResource: - if not isinstance(prefix, str): - raise TypeError("Prefix must be str") - prefix = prefix.rstrip('/') - if not prefix: - raise ValueError("Prefix cannot be empty") - factory = partial(PrefixedSubAppResource, prefix, subapp) - return self._add_subapp(factory, subapp) - - def _add_subapp(self, - resource_factory: Callable[[], AbstractResource], - subapp: 'Application') -> AbstractResource: - if self.frozen: - raise RuntimeError( - "Cannot add sub application to frozen application") - if subapp.frozen: - raise RuntimeError("Cannot add frozen application") - resource = resource_factory() - self.router.register_resource(resource) - self._reg_subapp_signals(subapp) - self._subapps.append(subapp) - subapp.pre_freeze() - if self._loop is not None: - subapp._set_loop(self._loop) - return resource - - def add_domain(self, domain: str, - subapp: 'Application') -> AbstractResource: - if not isinstance(domain, str): - raise TypeError("Domain must be str") - elif '*' in domain: - rule = MaskDomain(domain) # type: Domain - else: - rule = Domain(domain) - factory = partial(MatchedSubAppResource, rule, subapp) - return self._add_subapp(factory, subapp) - - def add_routes(self, routes: Iterable[AbstractRouteDef]) -> None: - self.router.add_routes(routes) - - @property - def on_response_prepare(self) -> _RespPrepareSignal: - return self._on_response_prepare - - @property - def on_startup(self) -> _AppSignal: - return self._on_startup - - @property - def on_shutdown(self) -> _AppSignal: - return self._on_shutdown - - @property - def on_cleanup(self) -> _AppSignal: - return self._on_cleanup - - @property - def cleanup_ctx(self) -> 'CleanupContext': - return self._cleanup_ctx - - @property - def router(self) -> UrlDispatcher: - return self._router - - @property - def middlewares(self) -> _Middlewares: - return self._middlewares - - def _make_handler(self, *, - loop: Optional[asyncio.AbstractEventLoop]=None, - access_log_class: Type[ - AbstractAccessLogger]=AccessLogger, - **kwargs: Any) -> Server: - - if not issubclass(access_log_class, AbstractAccessLogger): - raise TypeError( - 'access_log_class must be subclass of ' - 'aiohttp.abc.AbstractAccessLogger, got {}'.format( - access_log_class)) - - self._set_loop(loop) - self.freeze() - - kwargs['debug'] = self._debug - kwargs['access_log_class'] = access_log_class - if self._handler_args: - for k, v in self._handler_args.items(): - kwargs[k] = v - - return Server(self._handle, # type: ignore - request_factory=self._make_request, - loop=self._loop, **kwargs) - - def make_handler(self, *, - loop: Optional[asyncio.AbstractEventLoop]=None, - access_log_class: Type[ - AbstractAccessLogger]=AccessLogger, - **kwargs: Any) -> Server: - - warnings.warn("Application.make_handler(...) is deprecated, " - "use AppRunner API instead", - DeprecationWarning, - stacklevel=2) - - return self._make_handler(loop=loop, - access_log_class=access_log_class, - **kwargs) - - async def startup(self) -> None: - """Causes on_startup signal - - Should be called in the event loop along with the request handler. - """ - await self.on_startup.send(self) - - async def shutdown(self) -> None: - """Causes on_shutdown signal - - Should be called before cleanup() - """ - await self.on_shutdown.send(self) - - async def cleanup(self) -> None: - """Causes on_cleanup signal - - Should be called after shutdown() - """ - await self.on_cleanup.send(self) - - def _make_request(self, message: RawRequestMessage, - payload: StreamReader, - protocol: RequestHandler, - writer: AbstractStreamWriter, - task: 'asyncio.Task[None]', - _cls: Type[Request]=Request) -> Request: - return _cls( - message, payload, protocol, writer, task, - self._loop, - client_max_size=self._client_max_size) - - def _prepare_middleware(self) -> Iterator[Tuple[_Middleware, bool]]: - for m in reversed(self._middlewares): - if getattr(m, '__middleware_version__', None) == 1: - yield m, True - else: - warnings.warn('old-style middleware "{!r}" deprecated, ' - 'see #2252'.format(m), - DeprecationWarning, stacklevel=2) - yield m, False - - yield _fix_request_current_app(self), True - - async def _handle(self, request: Request) -> StreamResponse: - loop = asyncio.get_event_loop() - debug = loop.get_debug() - match_info = await self._router.resolve(request) - if debug: # pragma: no cover - if not isinstance(match_info, AbstractMatchInfo): - raise TypeError("match_info should be AbstractMatchInfo " - "instance, not {!r}".format(match_info)) - match_info.add_app(self) - - match_info.freeze() - - resp = None - request._match_info = match_info # type: ignore - expect = request.headers.get(hdrs.EXPECT) - if expect: - resp = await match_info.expect_handler(request) - await request.writer.drain() - - if resp is None: - handler = match_info.handler - - if self._run_middlewares: - for app in match_info.apps[::-1]: - for m, new_style in app._middlewares_handlers: # type: ignore # noqa - if new_style: - handler = partial(m, handler=handler) - else: - handler = await m(app, handler) # type: ignore - - resp = await handler(request) - - return resp - - def __call__(self) -> 'Application': - """gunicorn compatibility""" - return self - - def __repr__(self) -> str: - return "".format(id(self)) - - def __bool__(self) -> bool: - return True - - -class CleanupError(RuntimeError): - @property - def exceptions(self) -> List[BaseException]: - return self.args[1] - - -if TYPE_CHECKING: # pragma: no cover - _CleanupContextBase = FrozenList[Callable[[Application], - AsyncIterator[None]]] -else: - _CleanupContextBase = FrozenList - - -class CleanupContext(_CleanupContextBase): - - def __init__(self) -> None: - super().__init__() - self._exits = [] # type: List[AsyncIterator[None]] - - async def _on_startup(self, app: Application) -> None: - for cb in self: - it = cb(app).__aiter__() - await it.__anext__() - self._exits.append(it) - - async def _on_cleanup(self, app: Application) -> None: - errors = [] - for it in reversed(self._exits): - try: - await it.__anext__() - except StopAsyncIteration: - pass - except Exception as exc: - errors.append(exc) - else: - errors.append(RuntimeError("{!r} has more than one 'yield'" - .format(it))) - if errors: - if len(errors) == 1: - raise errors[0] - else: - raise CleanupError("Multiple errors on cleanup stage", errors) diff --git a/venv/Lib/site-packages/aiohttp/web_exceptions.py b/venv/Lib/site-packages/aiohttp/web_exceptions.py index 4d205299..b886697a 100644 --- a/venv/Lib/site-packages/aiohttp/web_exceptions.py +++ b/venv/Lib/site-packages/aiohttp/web_exceptions.py @@ -1,10 +1,4 @@ -import warnings -from typing import Any, Dict, Iterable, List, Optional, Set # noqa - -from yarl import URL - -from .typedefs import LooseHeaders, StrOrURL -from .web_response import Response +from .web_reqrep import Response __all__ = ( 'HTTPException', @@ -46,8 +40,6 @@ __all__ = ( 'HTTPRequestRangeNotSatisfiable', 'HTTPExpectationFailed', 'HTTPMisdirectedRequest', - 'HTTPUnprocessableEntity', - 'HTTPFailedDependency', 'HTTPUpgradeRequired', 'HTTPPreconditionRequired', 'HTTPTooManyRequests', @@ -61,7 +53,6 @@ __all__ = ( 'HTTPGatewayTimeout', 'HTTPVersionNotSupported', 'HTTPVariantAlsoNegotiates', - 'HTTPInsufficientStorage', 'HTTPNotExtended', 'HTTPNetworkAuthenticationRequired', ) @@ -76,21 +67,11 @@ class HTTPException(Response, Exception): # You should set in subclasses: # status = 200 - status_code = -1 + status_code = None empty_body = False - __http_exception__ = True - - def __init__(self, *, - headers: Optional[LooseHeaders]=None, - reason: Optional[str]=None, - body: Any=None, - text: Optional[str]=None, - content_type: Optional[str]=None) -> None: - if body is not None: - warnings.warn( - "body argument is deprecated for http web exceptions", - DeprecationWarning) + def __init__(self, *, headers=None, reason=None, + body=None, text=None, content_type=None): Response.__init__(self, status=self.status_code, headers=headers, reason=reason, body=body, text=text, content_type=content_type) @@ -98,9 +79,6 @@ class HTTPException(Response, Exception): if self.body is None and not self.empty_body: self.text = "{}: {}".format(self.status, self.reason) - def __bool__(self) -> bool: - return True - class HTTPError(HTTPException): """Base class for exceptions with status codes in the 400s and 500s.""" @@ -151,19 +129,13 @@ class HTTPPartialContent(HTTPSuccessful): class _HTTPMove(HTTPRedirection): - def __init__(self, - location: StrOrURL, - *, - headers: Optional[LooseHeaders]=None, - reason: Optional[str]=None, - body: Any=None, - text: Optional[str]=None, - content_type: Optional[str]=None) -> None: + def __init__(self, location, *, headers=None, reason=None, + body=None, text=None, content_type=None): if not location: raise ValueError("HTTP redirects need a location to redirect to.") super().__init__(headers=headers, reason=reason, body=body, text=text, content_type=content_type) - self.headers['Location'] = str(URL(location)) + self.headers['Location'] = location self.location = location @@ -236,20 +208,13 @@ class HTTPNotFound(HTTPClientError): class HTTPMethodNotAllowed(HTTPClientError): status_code = 405 - def __init__(self, - method: str, - allowed_methods: Iterable[str], - *, - headers: Optional[LooseHeaders]=None, - reason: Optional[str]=None, - body: Any=None, - text: Optional[str]=None, - content_type: Optional[str]=None) -> None: + def __init__(self, method, allowed_methods, *, headers=None, reason=None, + body=None, text=None, content_type=None): allow = ','.join(sorted(allowed_methods)) super().__init__(headers=headers, reason=reason, body=body, text=text, content_type=content_type) self.headers['Allow'] = allow - self.allowed_methods = set(allowed_methods) # type: Set[str] + self.allowed_methods = allowed_methods self.method = method.upper() @@ -284,17 +249,6 @@ class HTTPPreconditionFailed(HTTPClientError): class HTTPRequestEntityTooLarge(HTTPClientError): status_code = 413 - def __init__(self, - max_size: float, - actual_size: float, - **kwargs: Any) -> None: - kwargs.setdefault( - 'text', - 'Maximum request body size {} exceeded, ' - 'actual body size {}'.format(max_size, actual_size) - ) - super().__init__(**kwargs) - class HTTPRequestURITooLong(HTTPClientError): status_code = 414 @@ -316,14 +270,6 @@ class HTTPMisdirectedRequest(HTTPClientError): status_code = 421 -class HTTPUnprocessableEntity(HTTPClientError): - status_code = 422 - - -class HTTPFailedDependency(HTTPClientError): - status_code = 424 - - class HTTPUpgradeRequired(HTTPClientError): status_code = 426 @@ -343,14 +289,8 @@ class HTTPRequestHeaderFieldsTooLarge(HTTPClientError): class HTTPUnavailableForLegalReasons(HTTPClientError): status_code = 451 - def __init__(self, - link: str, - *, - headers: Optional[LooseHeaders]=None, - reason: Optional[str]=None, - body: Any=None, - text: Optional[str]=None, - content_type: Optional[str]=None) -> None: + def __init__(self, link, *, headers=None, reason=None, + body=None, text=None, content_type=None): super().__init__(headers=headers, reason=reason, body=body, text=text, content_type=content_type) self.headers['Link'] = '<%s>; rel="blocked-by"' % link @@ -401,10 +341,6 @@ class HTTPVariantAlsoNegotiates(HTTPServerError): status_code = 506 -class HTTPInsufficientStorage(HTTPServerError): - status_code = 507 - - class HTTPNotExtended(HTTPServerError): status_code = 510 diff --git a/venv/Lib/site-packages/aiohttp/web_fileresponse.py b/venv/Lib/site-packages/aiohttp/web_fileresponse.py deleted file mode 100644 index c6968cca..00000000 --- a/venv/Lib/site-packages/aiohttp/web_fileresponse.py +++ /dev/null @@ -1,346 +0,0 @@ -import asyncio -import mimetypes -import os -import pathlib -from functools import partial -from typing import ( # noqa - IO, - TYPE_CHECKING, - Any, - Awaitable, - Callable, - List, - Optional, - Union, - cast, -) - -from . import hdrs -from .abc import AbstractStreamWriter -from .base_protocol import BaseProtocol -from .helpers import set_exception, set_result -from .http_writer import StreamWriter -from .log import server_logger -from .typedefs import LooseHeaders -from .web_exceptions import ( - HTTPNotModified, - HTTPPartialContent, - HTTPPreconditionFailed, - HTTPRequestRangeNotSatisfiable, -) -from .web_response import StreamResponse - -__all__ = ('FileResponse',) - -if TYPE_CHECKING: # pragma: no cover - from .web_request import BaseRequest # noqa - - -_T_OnChunkSent = Optional[Callable[[bytes], Awaitable[None]]] - - -NOSENDFILE = bool(os.environ.get("AIOHTTP_NOSENDFILE")) - - -class SendfileStreamWriter(StreamWriter): - - def __init__(self, - protocol: BaseProtocol, - loop: asyncio.AbstractEventLoop, - fobj: IO[Any], - count: int, - on_chunk_sent: _T_OnChunkSent=None) -> None: - super().__init__(protocol, loop, on_chunk_sent) - self._sendfile_buffer = [] # type: List[bytes] - self._fobj = fobj - self._count = count - self._offset = fobj.tell() - self._in_fd = fobj.fileno() - - def _write(self, chunk: bytes) -> None: - # we overwrite StreamWriter._write, so nothing can be appended to - # _buffer, and nothing is written to the transport directly by the - # parent class - self.output_size += len(chunk) - self._sendfile_buffer.append(chunk) - - def _sendfile_cb(self, fut: 'asyncio.Future[None]', out_fd: int) -> None: - if fut.cancelled(): - return - try: - if self._do_sendfile(out_fd): - set_result(fut, None) - except Exception as exc: - set_exception(fut, exc) - - def _do_sendfile(self, out_fd: int) -> bool: - try: - n = os.sendfile(out_fd, - self._in_fd, - self._offset, - self._count) - if n == 0: # in_fd EOF reached - n = self._count - except (BlockingIOError, InterruptedError): - n = 0 - self.output_size += n - self._offset += n - self._count -= n - assert self._count >= 0 - return self._count == 0 - - def _done_fut(self, out_fd: int, fut: 'asyncio.Future[None]') -> None: - self.loop.remove_writer(out_fd) - - async def sendfile(self) -> None: - assert self.transport is not None - out_socket = self.transport.get_extra_info('socket').dup() - out_socket.setblocking(False) - out_fd = out_socket.fileno() - - loop = self.loop - data = b''.join(self._sendfile_buffer) - try: - await loop.sock_sendall(out_socket, data) - if not self._do_sendfile(out_fd): - fut = loop.create_future() - fut.add_done_callback(partial(self._done_fut, out_fd)) - loop.add_writer(out_fd, self._sendfile_cb, fut, out_fd) - await fut - except asyncio.CancelledError: - raise - except Exception: - server_logger.debug('Socket error') - self.transport.close() - finally: - out_socket.close() - - await super().write_eof() - - async def write_eof(self, chunk: bytes=b'') -> None: - pass - - -class FileResponse(StreamResponse): - """A response object can be used to send files.""" - - def __init__(self, path: Union[str, pathlib.Path], - chunk_size: int=256*1024, - status: int=200, - reason: Optional[str]=None, - headers: Optional[LooseHeaders]=None) -> None: - super().__init__(status=status, reason=reason, headers=headers) - - if isinstance(path, str): - path = pathlib.Path(path) - - self._path = path - self._chunk_size = chunk_size - - async def _sendfile_system(self, request: 'BaseRequest', - fobj: IO[Any], - count: int) -> AbstractStreamWriter: - # Write count bytes of fobj to resp using - # the os.sendfile system call. - # - # For details check - # https://github.com/KeepSafe/aiohttp/issues/1177 - # See https://github.com/KeepSafe/aiohttp/issues/958 for details - # - # request should be an aiohttp.web.Request instance. - # fobj should be an open file object. - # count should be an integer > 0. - - transport = request.transport - assert transport is not None - if (transport.get_extra_info("sslcontext") or - transport.get_extra_info("socket") is None or - self.compression): - writer = await self._sendfile_fallback(request, fobj, count) - else: - writer = SendfileStreamWriter( - request.protocol, - request._loop, - fobj, - count - ) - request._payload_writer = writer - - await super().prepare(request) - await writer.sendfile() - - return writer - - async def _sendfile_fallback(self, request: 'BaseRequest', - fobj: IO[Any], - count: int) -> AbstractStreamWriter: - # Mimic the _sendfile_system() method, but without using the - # os.sendfile() system call. This should be used on systems - # that don't support the os.sendfile(). - - # To keep memory usage low,fobj is transferred in chunks - # controlled by the constructor's chunk_size argument. - - writer = await super().prepare(request) - assert writer is not None - - chunk_size = self._chunk_size - loop = asyncio.get_event_loop() - - chunk = await loop.run_in_executor(None, fobj.read, chunk_size) - while chunk: - await writer.write(chunk) - count = count - chunk_size - if count <= 0: - break - chunk = await loop.run_in_executor( - None, fobj.read, min(chunk_size, count) - ) - - await writer.drain() - return writer - - if hasattr(os, "sendfile") and not NOSENDFILE: # pragma: no cover - _sendfile = _sendfile_system - else: # pragma: no cover - _sendfile = _sendfile_fallback - - async def prepare( - self, - request: 'BaseRequest' - ) -> Optional[AbstractStreamWriter]: - filepath = self._path - - gzip = False - if 'gzip' in request.headers.get(hdrs.ACCEPT_ENCODING, ''): - gzip_path = filepath.with_name(filepath.name + '.gz') - - if gzip_path.is_file(): - filepath = gzip_path - gzip = True - - loop = asyncio.get_event_loop() - st = await loop.run_in_executor(None, filepath.stat) - - modsince = request.if_modified_since - if modsince is not None and st.st_mtime <= modsince.timestamp(): - self.set_status(HTTPNotModified.status_code) - self._length_check = False - # Delete any Content-Length headers provided by user. HTTP 304 - # should always have empty response body - return await super().prepare(request) - - unmodsince = request.if_unmodified_since - if unmodsince is not None and st.st_mtime > unmodsince.timestamp(): - self.set_status(HTTPPreconditionFailed.status_code) - return await super().prepare(request) - - if hdrs.CONTENT_TYPE not in self.headers: - ct, encoding = mimetypes.guess_type(str(filepath)) - if not ct: - ct = 'application/octet-stream' - should_set_ct = True - else: - encoding = 'gzip' if gzip else None - should_set_ct = False - - status = self._status - file_size = st.st_size - count = file_size - - start = None - - ifrange = request.if_range - if ifrange is None or st.st_mtime <= ifrange.timestamp(): - # If-Range header check: - # condition = cached date >= last modification date - # return 206 if True else 200. - # if False: - # Range header would not be processed, return 200 - # if True but Range header missing - # return 200 - try: - rng = request.http_range - start = rng.start - end = rng.stop - except ValueError: - # https://tools.ietf.org/html/rfc7233: - # A server generating a 416 (Range Not Satisfiable) response to - # a byte-range request SHOULD send a Content-Range header field - # with an unsatisfied-range value. - # The complete-length in a 416 response indicates the current - # length of the selected representation. - # - # Will do the same below. Many servers ignore this and do not - # send a Content-Range header with HTTP 416 - self.headers[hdrs.CONTENT_RANGE] = 'bytes */{0}'.format( - file_size) - self.set_status(HTTPRequestRangeNotSatisfiable.status_code) - return await super().prepare(request) - - # If a range request has been made, convert start, end slice - # notation into file pointer offset and count - if start is not None or end is not None: - if start < 0 and end is None: # return tail of file - start += file_size - if start < 0: - # if Range:bytes=-1000 in request header but file size - # is only 200, there would be trouble without this - start = 0 - count = file_size - start - else: - # rfc7233:If the last-byte-pos value is - # absent, or if the value is greater than or equal to - # the current length of the representation data, - # the byte range is interpreted as the remainder - # of the representation (i.e., the server replaces the - # value of last-byte-pos with a value that is one less than - # the current length of the selected representation). - count = min(end if end is not None else file_size, - file_size) - start - - if start >= file_size: - # HTTP 416 should be returned in this case. - # - # According to https://tools.ietf.org/html/rfc7233: - # If a valid byte-range-set includes at least one - # byte-range-spec with a first-byte-pos that is less than - # the current length of the representation, or at least one - # suffix-byte-range-spec with a non-zero suffix-length, - # then the byte-range-set is satisfiable. Otherwise, the - # byte-range-set is unsatisfiable. - self.headers[hdrs.CONTENT_RANGE] = 'bytes */{0}'.format( - file_size) - self.set_status(HTTPRequestRangeNotSatisfiable.status_code) - return await super().prepare(request) - - status = HTTPPartialContent.status_code - # Even though you are sending the whole file, you should still - # return a HTTP 206 for a Range request. - self.set_status(status) - - if should_set_ct: - self.content_type = ct # type: ignore - if encoding: - self.headers[hdrs.CONTENT_ENCODING] = encoding - if gzip: - self.headers[hdrs.VARY] = hdrs.ACCEPT_ENCODING - self.last_modified = st.st_mtime # type: ignore - self.content_length = count - - self.headers[hdrs.ACCEPT_RANGES] = 'bytes' - - real_start = cast(int, start) - - if status == HTTPPartialContent.status_code: - self.headers[hdrs.CONTENT_RANGE] = 'bytes {0}-{1}/{2}'.format( - real_start, real_start + count - 1, file_size) - - fobj = await loop.run_in_executor(None, filepath.open, 'rb') - if start: # be aware that start could be None or int=0 here. - await loop.run_in_executor(None, fobj.seek, start) - - try: - return await self._sendfile(request, fobj, count) - finally: - await loop.run_in_executor(None, fobj.close) diff --git a/venv/Lib/site-packages/aiohttp/web_log.py b/venv/Lib/site-packages/aiohttp/web_log.py deleted file mode 100644 index 5d7db16f..00000000 --- a/venv/Lib/site-packages/aiohttp/web_log.py +++ /dev/null @@ -1,235 +0,0 @@ -import datetime -import functools -import logging -import os -import re -from collections import namedtuple -from typing import Any, Callable, Dict, Iterable, List, Tuple # noqa - -from .abc import AbstractAccessLogger -from .web_request import BaseRequest -from .web_response import StreamResponse - -KeyMethod = namedtuple('KeyMethod', 'key method') - - -class AccessLogger(AbstractAccessLogger): - """Helper object to log access. - - Usage: - log = logging.getLogger("spam") - log_format = "%a %{User-Agent}i" - access_logger = AccessLogger(log, log_format) - access_logger.log(request, response, time) - - Format: - %% The percent sign - %a Remote IP-address (IP-address of proxy if using reverse proxy) - %t Time when the request was started to process - %P The process ID of the child that serviced the request - %r First line of request - %s Response status code - %b Size of response in bytes, including HTTP headers - %T Time taken to serve the request, in seconds - %Tf Time taken to serve the request, in seconds with floating fraction - in .06f format - %D Time taken to serve the request, in microseconds - %{FOO}i request.headers['FOO'] - %{FOO}o response.headers['FOO'] - %{FOO}e os.environ['FOO'] - - """ - LOG_FORMAT_MAP = { - 'a': 'remote_address', - 't': 'request_start_time', - 'P': 'process_id', - 'r': 'first_request_line', - 's': 'response_status', - 'b': 'response_size', - 'T': 'request_time', - 'Tf': 'request_time_frac', - 'D': 'request_time_micro', - 'i': 'request_header', - 'o': 'response_header', - } - - LOG_FORMAT = '%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"' - FORMAT_RE = re.compile(r'%(\{([A-Za-z0-9\-_]+)\}([ioe])|[atPrsbOD]|Tf?)') - CLEANUP_RE = re.compile(r'(%[^s])') - _FORMAT_CACHE = {} # type: Dict[str, Tuple[str, List[KeyMethod]]] - - def __init__(self, logger: logging.Logger, - log_format: str=LOG_FORMAT) -> None: - """Initialise the logger. - - logger is a logger object to be used for logging. - log_format is a string with apache compatible log format description. - - """ - super().__init__(logger, log_format=log_format) - - _compiled_format = AccessLogger._FORMAT_CACHE.get(log_format) - if not _compiled_format: - _compiled_format = self.compile_format(log_format) - AccessLogger._FORMAT_CACHE[log_format] = _compiled_format - - self._log_format, self._methods = _compiled_format - - def compile_format(self, log_format: str) -> Tuple[str, List[KeyMethod]]: - """Translate log_format into form usable by modulo formatting - - All known atoms will be replaced with %s - Also methods for formatting of those atoms will be added to - _methods in appropriate order - - For example we have log_format = "%a %t" - This format will be translated to "%s %s" - Also contents of _methods will be - [self._format_a, self._format_t] - These method will be called and results will be passed - to translated string format. - - Each _format_* method receive 'args' which is list of arguments - given to self.log - - Exceptions are _format_e, _format_i and _format_o methods which - also receive key name (by functools.partial) - - """ - # list of (key, method) tuples, we don't use an OrderedDict as users - # can repeat the same key more than once - methods = list() - - for atom in self.FORMAT_RE.findall(log_format): - if atom[1] == '': - format_key1 = self.LOG_FORMAT_MAP[atom[0]] - m = getattr(AccessLogger, '_format_%s' % atom[0]) - key_method = KeyMethod(format_key1, m) - else: - format_key2 = (self.LOG_FORMAT_MAP[atom[2]], atom[1]) - m = getattr(AccessLogger, '_format_%s' % atom[2]) - key_method = KeyMethod(format_key2, - functools.partial(m, atom[1])) - - methods.append(key_method) - - log_format = self.FORMAT_RE.sub(r'%s', log_format) - log_format = self.CLEANUP_RE.sub(r'%\1', log_format) - return log_format, methods - - @staticmethod - def _format_i(key: str, - request: BaseRequest, - response: StreamResponse, - time: float) -> str: - if request is None: - return '(no headers)' - - # suboptimal, make istr(key) once - return request.headers.get(key, '-') - - @staticmethod - def _format_o(key: str, - request: BaseRequest, - response: StreamResponse, - time: float) -> str: - # suboptimal, make istr(key) once - return response.headers.get(key, '-') - - @staticmethod - def _format_a(request: BaseRequest, - response: StreamResponse, - time: float) -> str: - if request is None: - return '-' - ip = request.remote - return ip if ip is not None else '-' - - @staticmethod - def _format_t(request: BaseRequest, - response: StreamResponse, - time: float) -> str: - now = datetime.datetime.utcnow() - start_time = now - datetime.timedelta(seconds=time) - return start_time.strftime('[%d/%b/%Y:%H:%M:%S +0000]') - - @staticmethod - def _format_P(request: BaseRequest, - response: StreamResponse, - time: float) -> str: - return "<%s>" % os.getpid() - - @staticmethod - def _format_r(request: BaseRequest, - response: StreamResponse, - time: float) -> str: - if request is None: - return '-' - return '%s %s HTTP/%s.%s' % (request.method, request.path_qs, - request.version.major, - request.version.minor) - - @staticmethod - def _format_s(request: BaseRequest, - response: StreamResponse, - time: float) -> int: - return response.status - - @staticmethod - def _format_b(request: BaseRequest, - response: StreamResponse, - time: float) -> int: - return response.body_length - - @staticmethod - def _format_T(request: BaseRequest, - response: StreamResponse, - time: float) -> str: - return str(round(time)) - - @staticmethod - def _format_Tf(request: BaseRequest, - response: StreamResponse, - time: float) -> str: - return '%06f' % time - - @staticmethod - def _format_D(request: BaseRequest, - response: StreamResponse, - time: float) -> str: - return str(round(time * 1000000)) - - def _format_line(self, - request: BaseRequest, - response: StreamResponse, - time: float) -> Iterable[Tuple[str, - Callable[[BaseRequest, - StreamResponse, - float], - str]]]: - return [(key, method(request, response, time)) - for key, method in self._methods] - - def log(self, - request: BaseRequest, - response: StreamResponse, - time: float) -> None: - try: - fmt_info = self._format_line(request, response, time) - - values = list() - extra = dict() - for key, value in fmt_info: - values.append(value) - - if key.__class__ is str: - extra[key] = value - else: - k1, k2 = key - dct = extra.get(k1, {}) # type: Any - dct[k2] = value - extra[k1] = dct - - self.logger.info(self._log_format % tuple(values), extra=extra) - except Exception: - self.logger.exception("Error in logging") diff --git a/venv/Lib/site-packages/aiohttp/web_middlewares.py b/venv/Lib/site-packages/aiohttp/web_middlewares.py deleted file mode 100644 index 2c7bf977..00000000 --- a/venv/Lib/site-packages/aiohttp/web_middlewares.py +++ /dev/null @@ -1,120 +0,0 @@ -import re -from typing import TYPE_CHECKING, Awaitable, Callable, Tuple, Type, TypeVar - -from .web_exceptions import HTTPPermanentRedirect, _HTTPMove -from .web_request import Request -from .web_response import StreamResponse -from .web_urldispatcher import SystemRoute - -__all__ = ( - 'middleware', - 'normalize_path_middleware', -) - -if TYPE_CHECKING: # pragma: no cover - from .web_app import Application # noqa - -_Func = TypeVar('_Func') - - -async def _check_request_resolves(request: Request, - path: str) -> Tuple[bool, Request]: - alt_request = request.clone(rel_url=path) - - match_info = await request.app.router.resolve(alt_request) - alt_request._match_info = match_info # type: ignore - - if match_info.http_exception is None: - return True, alt_request - - return False, request - - -def middleware(f: _Func) -> _Func: - f.__middleware_version__ = 1 # type: ignore - return f - - -_Handler = Callable[[Request], Awaitable[StreamResponse]] -_Middleware = Callable[[Request, _Handler], Awaitable[StreamResponse]] - - -def normalize_path_middleware( - *, append_slash: bool=True, remove_slash: bool=False, - merge_slashes: bool=True, - redirect_class: Type[_HTTPMove]=HTTPPermanentRedirect) -> _Middleware: - """ - Middleware factory which produces a middleware that normalizes - the path of a request. By normalizing it means: - - - Add or remove a trailing slash to the path. - - Double slashes are replaced by one. - - The middleware returns as soon as it finds a path that resolves - correctly. The order if both merge and append/remove are enabled is - 1) merge slashes - 2) append/remove slash - 3) both merge slashes and append/remove slash. - If the path resolves with at least one of those conditions, it will - redirect to the new path. - - Only one of `append_slash` and `remove_slash` can be enabled. If both - are `True` the factory will raise an assertion error - - If `append_slash` is `True` the middleware will append a slash when - needed. If a resource is defined with trailing slash and the request - comes without it, it will append it automatically. - - If `remove_slash` is `True`, `append_slash` must be `False`. When enabled - the middleware will remove trailing slashes and redirect if the resource - is defined - - If merge_slashes is True, merge multiple consecutive slashes in the - path into one. - """ - - correct_configuration = not (append_slash and remove_slash) - assert correct_configuration, "Cannot both remove and append slash" - - @middleware - async def impl(request: Request, handler: _Handler) -> StreamResponse: - if isinstance(request.match_info.route, SystemRoute): - paths_to_check = [] - if '?' in request.raw_path: - path, query = request.raw_path.split('?', 1) - query = '?' + query - else: - query = '' - path = request.raw_path - - if merge_slashes: - paths_to_check.append(re.sub('//+', '/', path)) - if append_slash and not request.path.endswith('/'): - paths_to_check.append(path + '/') - if remove_slash and request.path.endswith('/'): - paths_to_check.append(path[:-1]) - if merge_slashes and append_slash: - paths_to_check.append( - re.sub('//+', '/', path + '/')) - if merge_slashes and remove_slash: - merged_slashes = re.sub('//+', '/', path) - paths_to_check.append(merged_slashes[:-1]) - - for path in paths_to_check: - resolves, request = await _check_request_resolves( - request, path) - if resolves: - raise redirect_class(request.raw_path + query) - - return await handler(request) - - return impl - - -def _fix_request_current_app(app: 'Application') -> _Middleware: - - @middleware - async def impl(request: Request, handler: _Handler) -> StreamResponse: - with request.match_info.set_current_app(app): - return await handler(request) - return impl diff --git a/venv/Lib/site-packages/aiohttp/web_protocol.py b/venv/Lib/site-packages/aiohttp/web_protocol.py deleted file mode 100644 index 61192881..00000000 --- a/venv/Lib/site-packages/aiohttp/web_protocol.py +++ /dev/null @@ -1,599 +0,0 @@ -import asyncio -import asyncio.streams -import traceback -import warnings -from collections import deque -from contextlib import suppress -from html import escape as html_escape -from http import HTTPStatus -from logging import Logger -from typing import ( - TYPE_CHECKING, - Any, - Awaitable, - Callable, - Optional, - Type, - cast, -) - -import yarl - -from .abc import AbstractAccessLogger, AbstractStreamWriter -from .base_protocol import BaseProtocol -from .helpers import CeilTimeout, current_task -from .http import ( - HttpProcessingError, - HttpRequestParser, - HttpVersion10, - RawRequestMessage, - StreamWriter, -) -from .log import access_logger, server_logger -from .streams import EMPTY_PAYLOAD, StreamReader -from .tcp_helpers import tcp_keepalive -from .web_exceptions import HTTPException -from .web_log import AccessLogger -from .web_request import BaseRequest -from .web_response import Response, StreamResponse - -__all__ = ('RequestHandler', 'RequestPayloadError', 'PayloadAccessError') - -if TYPE_CHECKING: # pragma: no cover - from .web_server import Server # noqa - - -_RequestFactory = Callable[[RawRequestMessage, - StreamReader, - 'RequestHandler', - AbstractStreamWriter, - 'asyncio.Task[None]'], - BaseRequest] - -_RequestHandler = Callable[[BaseRequest], Awaitable[StreamResponse]] - - -ERROR = RawRequestMessage( - 'UNKNOWN', '/', HttpVersion10, {}, - {}, True, False, False, False, yarl.URL('/')) - - -class RequestPayloadError(Exception): - """Payload parsing error.""" - - -class PayloadAccessError(Exception): - """Payload was accessed after response was sent.""" - - -class RequestHandler(BaseProtocol): - """HTTP protocol implementation. - - RequestHandler handles incoming HTTP request. It reads request line, - request headers and request payload and calls handle_request() method. - By default it always returns with 404 response. - - RequestHandler handles errors in incoming request, like bad - status line, bad headers or incomplete payload. If any error occurs, - connection gets closed. - - :param keepalive_timeout: number of seconds before closing - keep-alive connection - :type keepalive_timeout: int or None - - :param bool tcp_keepalive: TCP keep-alive is on, default is on - - :param bool debug: enable debug mode - - :param logger: custom logger object - :type logger: aiohttp.log.server_logger - - :param access_log_class: custom class for access_logger - :type access_log_class: aiohttp.abc.AbstractAccessLogger - - :param access_log: custom logging object - :type access_log: aiohttp.log.server_logger - - :param str access_log_format: access log format string - - :param loop: Optional event loop - - :param int max_line_size: Optional maximum header line size - - :param int max_field_size: Optional maximum header field size - - :param int max_headers: Optional maximum header size - - """ - KEEPALIVE_RESCHEDULE_DELAY = 1 - - __slots__ = ('_request_count', '_keepalive', '_manager', - '_request_handler', '_request_factory', '_tcp_keepalive', - '_keepalive_time', '_keepalive_handle', '_keepalive_timeout', - '_lingering_time', '_messages', '_message_tail', - '_waiter', '_error_handler', '_task_handler', - '_upgrade', '_payload_parser', '_request_parser', - '_reading_paused', 'logger', 'debug', 'access_log', - 'access_logger', '_close', '_force_close') - - def __init__(self, manager: 'Server', *, - loop: asyncio.AbstractEventLoop, - keepalive_timeout: float=75., # NGINX default is 75 secs - tcp_keepalive: bool=True, - logger: Logger=server_logger, - access_log_class: Type[AbstractAccessLogger]=AccessLogger, - access_log: Logger=access_logger, - access_log_format: str=AccessLogger.LOG_FORMAT, - debug: bool=False, - max_line_size: int=8190, - max_headers: int=32768, - max_field_size: int=8190, - lingering_time: float=10.0): - - super().__init__(loop) - - self._request_count = 0 - self._keepalive = False - self._manager = manager # type: Optional[Server] - self._request_handler = manager.request_handler # type: Optional[_RequestHandler] # noqa - self._request_factory = manager.request_factory # type: Optional[_RequestFactory] # noqa - - self._tcp_keepalive = tcp_keepalive - # placeholder to be replaced on keepalive timeout setup - self._keepalive_time = 0.0 - self._keepalive_handle = None # type: Optional[asyncio.Handle] - self._keepalive_timeout = keepalive_timeout - self._lingering_time = float(lingering_time) - - self._messages = deque() # type: Any # Python 3.5 has no typing.Deque - self._message_tail = b'' - - self._waiter = None # type: Optional[asyncio.Future[None]] - self._error_handler = None # type: Optional[asyncio.Task[None]] - self._task_handler = None # type: Optional[asyncio.Task[None]] - - self._upgrade = False - self._payload_parser = None # type: Any - self._request_parser = HttpRequestParser( - self, loop, - max_line_size=max_line_size, - max_field_size=max_field_size, - max_headers=max_headers, - payload_exception=RequestPayloadError) # type: Optional[HttpRequestParser] # noqa - - self.logger = logger - self.debug = debug - self.access_log = access_log - if access_log: - self.access_logger = access_log_class( - access_log, access_log_format) # type: Optional[AbstractAccessLogger] # noqa - else: - self.access_logger = None - - self._close = False - self._force_close = False - - def __repr__(self) -> str: - return "<{} {}>".format( - self.__class__.__name__, - 'connected' if self.transport is not None else 'disconnected') - - @property - def keepalive_timeout(self) -> float: - return self._keepalive_timeout - - async def shutdown(self, timeout: Optional[float]=15.0) -> None: - """Worker process is about to exit, we need cleanup everything and - stop accepting requests. It is especially important for keep-alive - connections.""" - self._force_close = True - - if self._keepalive_handle is not None: - self._keepalive_handle.cancel() - - if self._waiter: - self._waiter.cancel() - - # wait for handlers - with suppress(asyncio.CancelledError, asyncio.TimeoutError): - with CeilTimeout(timeout, loop=self._loop): - if (self._error_handler is not None and - not self._error_handler.done()): - await self._error_handler - - if (self._task_handler is not None and - not self._task_handler.done()): - await self._task_handler - - # force-close non-idle handler - if self._task_handler is not None: - self._task_handler.cancel() - - if self.transport is not None: - self.transport.close() - self.transport = None - - def connection_made(self, transport: asyncio.BaseTransport) -> None: - super().connection_made(transport) - - real_transport = cast(asyncio.Transport, transport) - if self._tcp_keepalive: - tcp_keepalive(real_transport) - - self._task_handler = self._loop.create_task(self.start()) - assert self._manager is not None - self._manager.connection_made(self, real_transport) - - def connection_lost(self, exc: Optional[BaseException]) -> None: - if self._manager is None: - return - self._manager.connection_lost(self, exc) - - super().connection_lost(exc) - - self._manager = None - self._force_close = True - self._request_factory = None - self._request_handler = None - self._request_parser = None - - if self._keepalive_handle is not None: - self._keepalive_handle.cancel() - - if self._task_handler is not None: - self._task_handler.cancel() - - if self._error_handler is not None: - self._error_handler.cancel() - - self._task_handler = None - - if self._payload_parser is not None: - self._payload_parser.feed_eof() - self._payload_parser = None - - def set_parser(self, parser: Any) -> None: - # Actual type is WebReader - assert self._payload_parser is None - - self._payload_parser = parser - - if self._message_tail: - self._payload_parser.feed_data(self._message_tail) - self._message_tail = b'' - - def eof_received(self) -> None: - pass - - def data_received(self, data: bytes) -> None: - if self._force_close or self._close: - return - # parse http messages - if self._payload_parser is None and not self._upgrade: - assert self._request_parser is not None - try: - messages, upgraded, tail = self._request_parser.feed_data(data) - except HttpProcessingError as exc: - # something happened during parsing - self._error_handler = self._loop.create_task( - self.handle_parse_error( - StreamWriter(self, self._loop), - 400, exc, exc.message)) - self.close() - except Exception as exc: - # 500: internal error - self._error_handler = self._loop.create_task( - self.handle_parse_error( - StreamWriter(self, self._loop), - 500, exc)) - self.close() - else: - if messages: - # sometimes the parser returns no messages - for (msg, payload) in messages: - self._request_count += 1 - self._messages.append((msg, payload)) - - waiter = self._waiter - if waiter is not None: - if not waiter.done(): - # don't set result twice - waiter.set_result(None) - - self._upgrade = upgraded - if upgraded and tail: - self._message_tail = tail - - # no parser, just store - elif self._payload_parser is None and self._upgrade and data: - self._message_tail += data - - # feed payload - elif data: - eof, tail = self._payload_parser.feed_data(data) - if eof: - self.close() - - def keep_alive(self, val: bool) -> None: - """Set keep-alive connection mode. - - :param bool val: new state. - """ - self._keepalive = val - if self._keepalive_handle: - self._keepalive_handle.cancel() - self._keepalive_handle = None - - def close(self) -> None: - """Stop accepting new pipelinig messages and close - connection when handlers done processing messages""" - self._close = True - if self._waiter: - self._waiter.cancel() - - def force_close(self) -> None: - """Force close connection""" - self._force_close = True - if self._waiter: - self._waiter.cancel() - if self.transport is not None: - self.transport.close() - self.transport = None - - def log_access(self, - request: BaseRequest, - response: StreamResponse, - time: float) -> None: - if self.access_logger is not None: - self.access_logger.log(request, response, time) - - def log_debug(self, *args: Any, **kw: Any) -> None: - if self.debug: - self.logger.debug(*args, **kw) - - def log_exception(self, *args: Any, **kw: Any) -> None: - self.logger.exception(*args, **kw) - - def _process_keepalive(self) -> None: - if self._force_close or not self._keepalive: - return - - next = self._keepalive_time + self._keepalive_timeout - - # handler in idle state - if self._waiter: - if self._loop.time() > next: - self.force_close() - return - - # not all request handlers are done, - # reschedule itself to next second - self._keepalive_handle = self._loop.call_later( - self.KEEPALIVE_RESCHEDULE_DELAY, self._process_keepalive) - - async def start(self) -> None: - """Process incoming request. - - It reads request line, request headers and request payload, then - calls handle_request() method. Subclass has to override - handle_request(). start() handles various exceptions in request - or response handling. Connection is being closed always unless - keep_alive(True) specified. - """ - loop = self._loop - handler = self._task_handler - assert handler is not None - manager = self._manager - assert manager is not None - keepalive_timeout = self._keepalive_timeout - resp = None - assert self._request_factory is not None - assert self._request_handler is not None - - while not self._force_close: - if not self._messages: - try: - # wait for next request - self._waiter = loop.create_future() - await self._waiter - except asyncio.CancelledError: - break - finally: - self._waiter = None - - message, payload = self._messages.popleft() - - if self.access_log: - now = loop.time() - - manager.requests_count += 1 - writer = StreamWriter(self, loop) - request = self._request_factory( - message, payload, self, writer, handler) - try: - # a new task is used for copy context vars (#3406) - task = self._loop.create_task( - self._request_handler(request)) - try: - resp = await task - except HTTPException as exc: - resp = exc - except (asyncio.CancelledError, ConnectionError): - self.log_debug('Ignored premature client disconnection') - break - except asyncio.TimeoutError as exc: - self.log_debug('Request handler timed out.', exc_info=exc) - resp = self.handle_error(request, 504) - except Exception as exc: - resp = self.handle_error(request, 500, exc) - else: - # Deprecation warning (See #2415) - if getattr(resp, '__http_exception__', False): - warnings.warn( - "returning HTTPException object is deprecated " - "(#2415) and will be removed, " - "please raise the exception instead", - DeprecationWarning) - - # Drop the processed task from asyncio.Task.all_tasks() early - del task - - if self.debug: - if not isinstance(resp, StreamResponse): - if resp is None: - raise RuntimeError("Missing return " - "statement on request handler") - else: - raise RuntimeError("Web-handler should return " - "a response instance, " - "got {!r}".format(resp)) - try: - prepare_meth = resp.prepare - except AttributeError: - if resp is None: - raise RuntimeError("Missing return " - "statement on request handler") - else: - raise RuntimeError("Web-handler should return " - "a response instance, " - "got {!r}".format(resp)) - try: - await prepare_meth(request) - await resp.write_eof() - except ConnectionError: - self.log_debug('Ignored premature client disconnection 2') - break - - # notify server about keep-alive - self._keepalive = bool(resp.keep_alive) - - # log access - if self.access_log: - self.log_access(request, resp, loop.time() - now) - - # check payload - if not payload.is_eof(): - lingering_time = self._lingering_time - if not self._force_close and lingering_time: - self.log_debug( - 'Start lingering close timer for %s sec.', - lingering_time) - - now = loop.time() - end_t = now + lingering_time - - with suppress( - asyncio.TimeoutError, asyncio.CancelledError): - while not payload.is_eof() and now < end_t: - with CeilTimeout(end_t - now, loop=loop): - # read and ignore - await payload.readany() - now = loop.time() - - # if payload still uncompleted - if not payload.is_eof() and not self._force_close: - self.log_debug('Uncompleted request.') - self.close() - - payload.set_exception(PayloadAccessError()) - - except asyncio.CancelledError: - self.log_debug('Ignored premature client disconnection ') - break - except RuntimeError as exc: - if self.debug: - self.log_exception( - 'Unhandled runtime exception', exc_info=exc) - self.force_close() - except Exception as exc: - self.log_exception('Unhandled exception', exc_info=exc) - self.force_close() - finally: - if self.transport is None and resp is not None: - self.log_debug('Ignored premature client disconnection.') - elif not self._force_close: - if self._keepalive and not self._close: - # start keep-alive timer - if keepalive_timeout is not None: - now = self._loop.time() - self._keepalive_time = now - if self._keepalive_handle is None: - self._keepalive_handle = loop.call_at( - now + keepalive_timeout, - self._process_keepalive) - else: - break - - # remove handler, close transport if no handlers left - if not self._force_close: - self._task_handler = None - if self.transport is not None and self._error_handler is None: - self.transport.close() - - def handle_error(self, - request: BaseRequest, - status: int=500, - exc: Optional[BaseException]=None, - message: Optional[str]=None) -> StreamResponse: - """Handle errors. - - Returns HTTP response with specific status code. Logs additional - information. It always closes current connection.""" - self.log_exception("Error handling request", exc_info=exc) - - ct = 'text/plain' - if status == HTTPStatus.INTERNAL_SERVER_ERROR: - title = '{0.value} {0.phrase}'.format( - HTTPStatus.INTERNAL_SERVER_ERROR - ) - msg = HTTPStatus.INTERNAL_SERVER_ERROR.description - tb = None - if self.debug: - with suppress(Exception): - tb = traceback.format_exc() - - if 'text/html' in request.headers.get('Accept', ''): - if tb: - tb = html_escape(tb) - msg = '

Traceback:

\n
{}
'.format(tb) - message = ( - "" - "{title}" - "\n

{title}

" - "\n{msg}\n\n" - ).format(title=title, msg=msg) - ct = 'text/html' - else: - if tb: - msg = tb - message = title + '\n\n' + msg - - resp = Response(status=status, text=message, content_type=ct) - resp.force_close() - - # some data already got sent, connection is broken - if request.writer.output_size > 0 or self.transport is None: - self.force_close() - - return resp - - async def handle_parse_error(self, - writer: AbstractStreamWriter, - status: int, - exc: Optional[BaseException]=None, - message: Optional[str]=None) -> None: - request = BaseRequest( # type: ignore - ERROR, - EMPTY_PAYLOAD, - self, writer, - current_task(), - self._loop) - - resp = self.handle_error(request, status, exc, message) - await resp.prepare(request) - await resp.write_eof() - - if self.transport is not None: - self.transport.close() - - self._error_handler = None diff --git a/venv/Lib/site-packages/aiohttp/web_reqrep.py b/venv/Lib/site-packages/aiohttp/web_reqrep.py new file mode 100644 index 00000000..ba24a40d --- /dev/null +++ b/venv/Lib/site-packages/aiohttp/web_reqrep.py @@ -0,0 +1,895 @@ +import asyncio +import binascii +import cgi +import collections +import datetime +import enum +import http.cookies +import io +import json +import math +import time +import warnings +from email.utils import parsedate +from types import MappingProxyType +from urllib.parse import parse_qsl, unquote, urlsplit + +from multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy + +from . import hdrs, multipart +from .helpers import reify, sentinel +from .protocol import Response as ResponseImpl +from .protocol import HttpVersion10, HttpVersion11 +from .streams import EOF_MARKER + +__all__ = ( + 'ContentCoding', 'Request', 'StreamResponse', 'Response', + 'json_response' +) + + +class HeadersMixin: + + _content_type = None + _content_dict = None + _stored_content_type = sentinel + + def _parse_content_type(self, raw): + self._stored_content_type = raw + if raw is None: + # default value according to RFC 2616 + self._content_type = 'application/octet-stream' + self._content_dict = {} + else: + self._content_type, self._content_dict = cgi.parse_header(raw) + + @property + def content_type(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE): + """The value of content part for Content-Type HTTP header.""" + raw = self.headers.get(_CONTENT_TYPE) + if self._stored_content_type != raw: + self._parse_content_type(raw) + return self._content_type + + @property + def charset(self, _CONTENT_TYPE=hdrs.CONTENT_TYPE): + """The value of charset part for Content-Type HTTP header.""" + raw = self.headers.get(_CONTENT_TYPE) + if self._stored_content_type != raw: + self._parse_content_type(raw) + return self._content_dict.get('charset') + + @property + def content_length(self, _CONTENT_LENGTH=hdrs.CONTENT_LENGTH): + """The value of Content-Length HTTP header.""" + l = self.headers.get(_CONTENT_LENGTH) + if l is None: + return None + else: + return int(l) + +FileField = collections.namedtuple('Field', 'name filename file content_type') + + +class ContentCoding(enum.Enum): + # The content codings that we have support for. + # + # Additional registered codings are listed at: + # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding + deflate = 'deflate' + gzip = 'gzip' + identity = 'identity' + + +############################################################ +# HTTP Request +############################################################ + + +class Request(dict, HeadersMixin): + + POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT, + hdrs.METH_TRACE, hdrs.METH_DELETE} + + def __init__(self, app, message, payload, transport, reader, writer, *, + secure_proxy_ssl_header=None): + self._app = app + self._message = message + self._transport = transport + self._reader = reader + self._writer = writer + self._post = None + self._post_files_cache = None + + # matchdict, route_name, handler + # or information about traversal lookup + self._match_info = None # initialized after route resolving + + self._payload = payload + + self._read_bytes = None + self._has_body = not payload.at_eof() + + self._secure_proxy_ssl_header = secure_proxy_ssl_header + + @reify + def scheme(self): + """A string representing the scheme of the request. + + 'http' or 'https'. + """ + if self._transport.get_extra_info('sslcontext'): + return 'https' + secure_proxy_ssl_header = self._secure_proxy_ssl_header + if secure_proxy_ssl_header is not None: + header, value = secure_proxy_ssl_header + if self.headers.get(header) == value: + return 'https' + return 'http' + + @reify + def method(self): + """Read only property for getting HTTP method. + + The value is upper-cased str like 'GET', 'POST', 'PUT' etc. + """ + return self._message.method + + @reify + def version(self): + """Read only property for getting HTTP version of request. + + Returns aiohttp.protocol.HttpVersion instance. + """ + return self._message.version + + @reify + def host(self): + """Read only property for getting *HOST* header of request. + + Returns str or None if HTTP request has no HOST header. + """ + return self._message.headers.get(hdrs.HOST) + + @reify + def path_qs(self): + """The URL including PATH_INFO and the query string. + + E.g, /app/blog?id=10 + """ + return self._message.path + + @reify + def _splitted_path(self): + url = '{}://{}{}'.format(self.scheme, self.host, self.path_qs) + return urlsplit(url) + + @reify + def raw_path(self): + """ The URL including raw *PATH INFO* without the host or scheme. + Warning, the path is unquoted and may contains non valid URL characters + + E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters`` + """ + return self._splitted_path.path + + @reify + def path(self): + """The URL including *PATH INFO* without the host or scheme. + + E.g., ``/app/blog`` + """ + return unquote(self.raw_path) + + @reify + def query_string(self): + """The query string in the URL. + + E.g., id=10 + """ + return self._splitted_path.query + + @reify + def GET(self): + """A multidict with all the variables in the query string. + + Lazy property. + """ + return MultiDictProxy(MultiDict(parse_qsl(self.query_string, + keep_blank_values=True))) + + @reify + def POST(self): + """A multidict with all the variables in the POST parameters. + + post() methods has to be called before using this attribute. + """ + if self._post is None: + raise RuntimeError("POST is not available before post()") + return self._post + + @reify + def headers(self): + """A case-insensitive multidict proxy with all headers.""" + return CIMultiDictProxy(self._message.headers) + + @reify + def raw_headers(self): + """A sequence of pars for all headers.""" + return tuple(self._message.raw_headers) + + @reify + def if_modified_since(self, _IF_MODIFIED_SINCE=hdrs.IF_MODIFIED_SINCE): + """The value of If-Modified-Since HTTP header, or None. + + This header is represented as a `datetime` object. + """ + httpdate = self.headers.get(_IF_MODIFIED_SINCE) + if httpdate is not None: + timetuple = parsedate(httpdate) + if timetuple is not None: + return datetime.datetime(*timetuple[:6], + tzinfo=datetime.timezone.utc) + return None + + @reify + def keep_alive(self): + """Is keepalive enabled by client?""" + if self.version < HttpVersion10: + return False + else: + return not self._message.should_close + + @property + def match_info(self): + """Result of route resolving.""" + return self._match_info + + @property + def app(self): + """Application instance.""" + return self._app + + @property + def transport(self): + """Transport used for request processing.""" + return self._transport + + @reify + def cookies(self): + """Return request cookies. + + A read-only dictionary-like object. + """ + raw = self.headers.get(hdrs.COOKIE, '') + parsed = http.cookies.SimpleCookie(raw) + return MappingProxyType( + {key: val.value for key, val in parsed.items()}) + + @property + def content(self): + """Return raw payload stream.""" + return self._payload + + @property + def has_body(self): + """Return True if request has HTTP BODY, False otherwise.""" + return self._has_body + + @asyncio.coroutine + def release(self): + """Release request. + + Eat unread part of HTTP BODY if present. + """ + chunk = yield from self._payload.readany() + while chunk is not EOF_MARKER or chunk: + chunk = yield from self._payload.readany() + + @asyncio.coroutine + def read(self): + """Read request body if present. + + Returns bytes object with full request content. + """ + if self._read_bytes is None: + body = bytearray() + while True: + chunk = yield from self._payload.readany() + body.extend(chunk) + if chunk is EOF_MARKER: + break + self._read_bytes = bytes(body) + return self._read_bytes + + @asyncio.coroutine + def text(self): + """Return BODY as text using encoding from .charset.""" + bytes_body = yield from self.read() + encoding = self.charset or 'utf-8' + return bytes_body.decode(encoding) + + @asyncio.coroutine + def json(self, *, loads=json.loads, loader=None): + """Return BODY as JSON.""" + if loader is not None: + warnings.warn( + "Using loader argument is deprecated, use loads instead", + DeprecationWarning) + loads = loader + body = yield from self.text() + return loads(body) + + @asyncio.coroutine + def multipart(self, *, reader=multipart.MultipartReader): + """Return async iterator to process BODY as multipart.""" + return reader(self.headers, self.content) + + @asyncio.coroutine + def post(self): + """Return POST parameters.""" + if self._post is not None: + return self._post + if self.method not in self.POST_METHODS: + self._post = MultiDictProxy(MultiDict()) + return self._post + + content_type = self.content_type + if (content_type not in ('', + 'application/x-www-form-urlencoded', + 'multipart/form-data')): + self._post = MultiDictProxy(MultiDict()) + return self._post + + if self.content_type.startswith('multipart/'): + warnings.warn('To process multipart requests use .multipart' + ' coroutine instead.', DeprecationWarning) + + body = yield from self.read() + content_charset = self.charset or 'utf-8' + + environ = {'REQUEST_METHOD': self.method, + 'CONTENT_LENGTH': str(len(body)), + 'QUERY_STRING': '', + 'CONTENT_TYPE': self.headers.get(hdrs.CONTENT_TYPE)} + + fs = cgi.FieldStorage(fp=io.BytesIO(body), + environ=environ, + keep_blank_values=True, + encoding=content_charset) + + supported_transfer_encoding = { + 'base64': binascii.a2b_base64, + 'quoted-printable': binascii.a2b_qp + } + + out = MultiDict() + _count = 1 + for field in fs.list or (): + transfer_encoding = field.headers.get( + hdrs.CONTENT_TRANSFER_ENCODING, None) + if field.filename: + ff = FileField(field.name, + field.filename, + field.file, # N.B. file closed error + field.type) + if self._post_files_cache is None: + self._post_files_cache = {} + self._post_files_cache[field.name+str(_count)] = field + _count += 1 + out.add(field.name, ff) + else: + value = field.value + if transfer_encoding in supported_transfer_encoding: + # binascii accepts bytes + value = value.encode('utf-8') + value = supported_transfer_encoding[ + transfer_encoding](value) + out.add(field.name, value) + + self._post = MultiDictProxy(out) + return self._post + + def copy(self): + raise NotImplementedError + + def __repr__(self): + ascii_encodable_path = self.path.encode('ascii', 'backslashreplace') \ + .decode('ascii') + return "<{} {} {} >".format(self.__class__.__name__, + self.method, ascii_encodable_path) + + +############################################################ +# HTTP Response classes +############################################################ + + +class StreamResponse(HeadersMixin): + + def __init__(self, *, status=200, reason=None, headers=None): + self._body = None + self._keep_alive = None + self._chunked = False + self._chunk_size = None + self._compression = False + self._compression_force = False + self._headers = CIMultiDict() + self._cookies = http.cookies.SimpleCookie() + self.set_status(status, reason) + + self._req = None + self._resp_impl = None + self._eof_sent = False + self._tcp_nodelay = True + self._tcp_cork = False + + if headers is not None: + self._headers.extend(headers) + self._parse_content_type(self._headers.get(hdrs.CONTENT_TYPE)) + self._generate_content_type_header() + + def _copy_cookies(self): + for cookie in self._cookies.values(): + value = cookie.output(header='')[1:] + self.headers.add(hdrs.SET_COOKIE, value) + + @property + def prepared(self): + return self._resp_impl is not None + + @property + def started(self): + warnings.warn('use Response.prepared instead', DeprecationWarning) + return self.prepared + + @property + def status(self): + return self._status + + @property + def chunked(self): + return self._chunked + + @property + def compression(self): + return self._compression + + @property + def reason(self): + return self._reason + + def set_status(self, status, reason=None): + self._status = int(status) + if reason is None: + reason = ResponseImpl.calc_reason(status) + self._reason = reason + + @property + def keep_alive(self): + return self._keep_alive + + def force_close(self): + self._keep_alive = False + + def enable_chunked_encoding(self, chunk_size=None): + """Enables automatic chunked transfer encoding.""" + self._chunked = True + self._chunk_size = chunk_size + + def enable_compression(self, force=None): + """Enables response compression encoding.""" + # Backwards compatibility for when force was a bool <0.17. + if type(force) == bool: + force = ContentCoding.deflate if force else ContentCoding.identity + elif force is not None: + assert isinstance(force, ContentCoding), ("force should one of " + "None, bool or " + "ContentEncoding") + + self._compression = True + self._compression_force = force + + @property + def headers(self): + return self._headers + + @property + def cookies(self): + return self._cookies + + def set_cookie(self, name, value, *, expires=None, + domain=None, max_age=None, path='/', + secure=None, httponly=None, version=None): + """Set or update response cookie. + + Sets new cookie or updates existent with new value. + Also updates only those params which are not None. + """ + + old = self._cookies.get(name) + if old is not None and old.coded_value == '': + # deleted cookie + self._cookies.pop(name, 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 + + if max_age is not None: + c['max-age'] = max_age + elif 'max-age' in c: + del c['max-age'] + + c['path'] = path + + if secure is not None: + c['secure'] = secure + if httponly is not None: + c['httponly'] = httponly + if version is not None: + c['version'] = version + + def del_cookie(self, name, *, domain=None, path='/'): + """Delete cookie. + + Creates new empty expired cookie. + """ + # TODO: do we need domain/path here? + self._cookies.pop(name, None) + 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): + # Just a placeholder for adding setter + return super().content_length + + @content_length.setter + def content_length(self, value): + if value is not None: + value = int(value) + # TODO: raise error if chunked enabled + self.headers[hdrs.CONTENT_LENGTH] = str(value) + else: + self.headers.pop(hdrs.CONTENT_LENGTH, None) + + @property + def content_type(self): + # Just a placeholder for adding setter + return super().content_type + + @content_type.setter + def content_type(self, value): + self.content_type # read header values if needed + self._content_type = str(value) + self._generate_content_type_header() + + @property + def charset(self): + # Just a placeholder for adding setter + return super().charset + + @charset.setter + def charset(self, value): + ctype = self.content_type # read header values if needed + if ctype == 'application/octet-stream': + raise RuntimeError("Setting charset for application/octet-stream " + "doesn't make sense, setup content_type first") + if value is None: + self._content_dict.pop('charset', None) + else: + self._content_dict['charset'] = str(value).lower() + self._generate_content_type_header() + + @property + def last_modified(self, _LAST_MODIFIED=hdrs.LAST_MODIFIED): + """The value of Last-Modified HTTP header, or None. + + This header is represented as a `datetime` object. + """ + httpdate = self.headers.get(_LAST_MODIFIED) + if httpdate is not None: + timetuple = parsedate(httpdate) + if timetuple is not None: + return datetime.datetime(*timetuple[:6], + tzinfo=datetime.timezone.utc) + return None + + @last_modified.setter + def last_modified(self, value): + if value is None: + self.headers.pop(hdrs.LAST_MODIFIED, None) + elif isinstance(value, (int, float)): + self.headers[hdrs.LAST_MODIFIED] = time.strftime( + "%a, %d %b %Y %H:%M:%S GMT", time.gmtime(math.ceil(value))) + elif isinstance(value, datetime.datetime): + self.headers[hdrs.LAST_MODIFIED] = time.strftime( + "%a, %d %b %Y %H:%M:%S GMT", value.utctimetuple()) + elif isinstance(value, str): + self.headers[hdrs.LAST_MODIFIED] = value + + @property + def tcp_nodelay(self): + return self._tcp_nodelay + + def set_tcp_nodelay(self, value): + value = bool(value) + self._tcp_nodelay = value + if value: + self._tcp_cork = False + if self._resp_impl is None: + return + if value: + self._resp_impl.transport.set_tcp_cork(False) + self._resp_impl.transport.set_tcp_nodelay(value) + + @property + def tcp_cork(self): + return self._tcp_cork + + def set_tcp_cork(self, value): + value = bool(value) + self._tcp_cork = value + if value: + self._tcp_nodelay = False + if self._resp_impl is None: + return + if value: + self._resp_impl.transport.set_tcp_nodelay(False) + self._resp_impl.transport.set_tcp_cork(value) + + def _generate_content_type_header(self, CONTENT_TYPE=hdrs.CONTENT_TYPE): + params = '; '.join("%s=%s" % i for i in self._content_dict.items()) + if params: + ctype = self._content_type + '; ' + params + else: + ctype = self._content_type + self.headers[CONTENT_TYPE] = ctype + + def _start_pre_check(self, request): + if self._resp_impl is not None: + if self._req is not request: + raise RuntimeError( + "Response has been started with different request.") + else: + return self._resp_impl + else: + return None + + def _do_start_compression(self, coding): + if coding != ContentCoding.identity: + self.headers[hdrs.CONTENT_ENCODING] = coding.value + self._resp_impl.add_compression_filter(coding.value) + self.content_length = None + + def _start_compression(self, request): + if self._compression_force: + self._do_start_compression(self._compression_force) + else: + accept_encoding = request.headers.get( + hdrs.ACCEPT_ENCODING, '').lower() + for coding in ContentCoding: + if coding.value in accept_encoding: + self._do_start_compression(coding) + return + + def start(self, request): + warnings.warn('use .prepare(request) instead', DeprecationWarning) + resp_impl = self._start_pre_check(request) + if resp_impl is not None: + return resp_impl + + return self._start(request) + + @asyncio.coroutine + def prepare(self, request): + resp_impl = self._start_pre_check(request) + if resp_impl is not None: + return resp_impl + yield from request.app.on_response_prepare.send(request, self) + + return self._start(request) + + def _start(self, request): + self._req = request + keep_alive = self._keep_alive + if keep_alive is None: + keep_alive = request.keep_alive + self._keep_alive = keep_alive + + resp_impl = self._resp_impl = ResponseImpl( + request._writer, + self._status, + request.version, + not keep_alive, + self._reason) + + self._copy_cookies() + + if self._compression: + self._start_compression(request) + + if self._chunked: + if request.version != HttpVersion11: + raise RuntimeError("Using chunked encoding is forbidden " + "for HTTP/{0.major}.{0.minor}".format( + request.version)) + resp_impl.enable_chunked_encoding() + if self._chunk_size: + resp_impl.add_chunking_filter(self._chunk_size) + + headers = self.headers.items() + for key, val in headers: + resp_impl.add_header(key, val) + + resp_impl.transport.set_tcp_nodelay(self._tcp_nodelay) + resp_impl.transport.set_tcp_cork(self._tcp_cork) + self._send_headers(resp_impl) + return resp_impl + + def _send_headers(self, resp_impl): + # Durty hack required for + # https://github.com/KeepSafe/aiohttp/issues/1093 + # File sender may override it + resp_impl.send_headers() + + def write(self, data): + assert isinstance(data, (bytes, bytearray, memoryview)), \ + "data argument must be byte-ish (%r)" % type(data) + + if self._eof_sent: + raise RuntimeError("Cannot call write() after write_eof()") + if self._resp_impl is None: + raise RuntimeError("Cannot call write() before start()") + + if data: + return self._resp_impl.write(data) + else: + return () + + @asyncio.coroutine + def drain(self): + if self._resp_impl is None: + raise RuntimeError("Response has not been started") + yield from self._resp_impl.transport.drain() + + @asyncio.coroutine + def write_eof(self): + if self._eof_sent: + return + if self._resp_impl is None: + raise RuntimeError("Response has not been started") + + yield from self._resp_impl.write_eof() + self._eof_sent = True + + def __repr__(self): + if self.started: + info = "{} {} ".format(self._req.method, self._req.path) + else: + info = "not started" + return "<{} {} {}>".format(self.__class__.__name__, + self.reason, info) + + +class Response(StreamResponse): + + def __init__(self, *, body=None, status=200, + reason=None, text=None, headers=None, content_type=None, + charset=None): + if body is not None and text is not None: + raise ValueError("body and text are not allowed together") + + if headers is None: + headers = CIMultiDict() + elif not isinstance(headers, (CIMultiDict, CIMultiDictProxy)): + headers = CIMultiDict(headers) + + if content_type is not None and ";" in content_type: + raise ValueError("charset must not be in content_type " + "argument") + + if text is not None: + if hdrs.CONTENT_TYPE in headers: + if content_type or charset: + raise ValueError("passing both Content-Type header and " + "content_type or charset params " + "is forbidden") + else: + # fast path for filling headers + if not isinstance(text, str): + raise TypeError("text argument must be str (%r)" % + type(text)) + if content_type is None: + content_type = 'text/plain' + if charset is None: + charset = 'utf-8' + headers[hdrs.CONTENT_TYPE] = ( + content_type + '; charset=' + charset) + body = text.encode(charset) + text = None + else: + if hdrs.CONTENT_TYPE in headers: + if content_type is not None or charset is not None: + raise ValueError("passing both Content-Type header and " + "content_type or charset params " + "is forbidden") + else: + if content_type is not None: + if charset is not None: + content_type += '; charset=' + charset + headers[hdrs.CONTENT_TYPE] = content_type + + super().__init__(status=status, reason=reason, headers=headers) + self.set_tcp_cork(True) + if text is not None: + self.text = text + else: + self.body = body + + @property + def body(self): + return self._body + + @body.setter + def body(self, body): + if body is not None and not isinstance(body, bytes): + raise TypeError("body argument must be bytes (%r)" % type(body)) + self._body = body + if body is not None: + self.content_length = len(body) + else: + self.content_length = 0 + + @property + def text(self): + if self._body is None: + return None + return self._body.decode(self.charset or 'utf-8') + + @text.setter + def text(self, text): + if text is not None and not isinstance(text, str): + raise TypeError("text argument must be str (%r)" % type(text)) + + if self.content_type == 'application/octet-stream': + self.content_type = 'text/plain' + if self.charset is None: + self.charset = 'utf-8' + + self.body = text.encode(self.charset) + + @asyncio.coroutine + def write_eof(self): + try: + body = self._body + if (body is not None and + self._req.method != hdrs.METH_HEAD and + self._status not in [204, 304]): + self.write(body) + finally: + self.set_tcp_nodelay(True) + yield from super().write_eof() + + +def json_response(data=sentinel, *, text=None, body=None, status=200, + reason=None, headers=None, content_type='application/json', + dumps=json.dumps): + if data is not sentinel: + if text or body: + raise ValueError( + "only one of data, text, or body should be specified" + ) + else: + text = dumps(data) + return Response(text=text, body=body, status=status, reason=reason, + headers=headers, content_type=content_type) diff --git a/venv/Lib/site-packages/aiohttp/web_request.py b/venv/Lib/site-packages/aiohttp/web_request.py deleted file mode 100644 index 596ff4ba..00000000 --- a/venv/Lib/site-packages/aiohttp/web_request.py +++ /dev/null @@ -1,754 +0,0 @@ -import asyncio -import datetime -import io -import re -import socket -import string -import tempfile -import types -import warnings -from email.utils import parsedate -from http.cookies import SimpleCookie -from types import MappingProxyType -from typing import ( # noqa - TYPE_CHECKING, - Any, - Dict, - Iterator, - Mapping, - MutableMapping, - Optional, - Tuple, - Union, - cast, -) -from urllib.parse import parse_qsl - -import attr -from multidict import CIMultiDict, CIMultiDictProxy, MultiDict, MultiDictProxy -from yarl import URL - -from . import hdrs -from .abc import AbstractStreamWriter -from .helpers import DEBUG, ChainMapProxy, HeadersMixin, reify, sentinel -from .http_parser import RawRequestMessage -from .multipart import BodyPartReader, MultipartReader -from .streams import EmptyStreamReader, StreamReader -from .typedefs import ( - DEFAULT_JSON_DECODER, - JSONDecoder, - LooseHeaders, - RawHeaders, - StrOrURL, -) -from .web_exceptions import HTTPRequestEntityTooLarge -from .web_response import StreamResponse - -__all__ = ('BaseRequest', 'FileField', 'Request') - - -if TYPE_CHECKING: # pragma: no cover - from .web_app import Application # noqa - from .web_urldispatcher import UrlMappingMatchInfo # noqa - from .web_protocol import RequestHandler # noqa - - -@attr.s(frozen=True, slots=True) -class FileField: - name = attr.ib(type=str) - filename = attr.ib(type=str) - file = attr.ib(type=io.BufferedReader) - content_type = attr.ib(type=str) - headers = attr.ib(type=CIMultiDictProxy) # type: CIMultiDictProxy[str] - - -_TCHAR = string.digits + string.ascii_letters + r"!#$%&'*+.^_`|~-" -# '-' at the end to prevent interpretation as range in a char class - -_TOKEN = r'[{tchar}]+'.format(tchar=_TCHAR) - -_QDTEXT = r'[{}]'.format( - r''.join(chr(c) for c in (0x09, 0x20, 0x21) + tuple(range(0x23, 0x7F)))) -# qdtext includes 0x5C to escape 0x5D ('\]') -# qdtext excludes obs-text (because obsoleted, and encoding not specified) - -_QUOTED_PAIR = r'\\[\t !-~]' - -_QUOTED_STRING = r'"(?:{quoted_pair}|{qdtext})*"'.format( - qdtext=_QDTEXT, quoted_pair=_QUOTED_PAIR) - -_FORWARDED_PAIR = ( - r'({token})=({token}|{quoted_string})(:\d{{1,4}})?'.format( - token=_TOKEN, - quoted_string=_QUOTED_STRING)) - -_QUOTED_PAIR_REPLACE_RE = re.compile(r'\\([\t !-~])') -# same pattern as _QUOTED_PAIR but contains a capture group - -_FORWARDED_PAIR_RE = re.compile(_FORWARDED_PAIR) - -############################################################ -# HTTP Request -############################################################ - - -class BaseRequest(MutableMapping[str, Any], HeadersMixin): - - POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT, - hdrs.METH_TRACE, hdrs.METH_DELETE} - - ATTRS = HeadersMixin.ATTRS | frozenset([ - '_message', '_protocol', '_payload_writer', '_payload', '_headers', - '_method', '_version', '_rel_url', '_post', '_read_bytes', - '_state', '_cache', '_task', '_client_max_size', '_loop', - '_transport_sslcontext', '_transport_peername']) - - def __init__(self, message: RawRequestMessage, - payload: StreamReader, protocol: 'RequestHandler', - payload_writer: AbstractStreamWriter, - task: 'asyncio.Task[None]', - loop: asyncio.AbstractEventLoop, - *, client_max_size: int=1024**2, - state: Optional[Dict[str, Any]]=None, - scheme: Optional[str]=None, - host: Optional[str]=None, - remote: Optional[str]=None) -> None: - if state is None: - state = {} - self._message = message - self._protocol = protocol - self._payload_writer = payload_writer - - self._payload = payload - self._headers = message.headers - self._method = message.method - self._version = message.version - self._rel_url = message.url - self._post = None # type: Optional[MultiDictProxy[Union[str, bytes, FileField]]] # noqa - self._read_bytes = None # type: Optional[bytes] - - self._state = state - self._cache = {} # type: Dict[str, Any] - self._task = task - self._client_max_size = client_max_size - self._loop = loop - - transport = self._protocol.transport - assert transport is not None - self._transport_sslcontext = transport.get_extra_info('sslcontext') - self._transport_peername = transport.get_extra_info('peername') - - if scheme is not None: - self._cache['scheme'] = scheme - if host is not None: - self._cache['host'] = host - if remote is not None: - self._cache['remote'] = remote - - def clone(self, *, method: str=sentinel, rel_url: StrOrURL=sentinel, - headers: LooseHeaders=sentinel, scheme: str=sentinel, - host: str=sentinel, - remote: str=sentinel) -> 'BaseRequest': - """Clone itself with replacement some attributes. - - Creates and returns a new instance of Request object. If no parameters - are given, an exact copy is returned. If a parameter is not passed, it - will reuse the one from the current request object. - - """ - - if self._read_bytes: - raise RuntimeError("Cannot clone request " - "after reading its content") - - dct = {} # type: Dict[str, Any] - if method is not sentinel: - dct['method'] = method - if rel_url is not sentinel: - new_url = URL(rel_url) - dct['url'] = new_url - dct['path'] = str(new_url) - if headers is not sentinel: - # a copy semantic - dct['headers'] = CIMultiDictProxy(CIMultiDict(headers)) - dct['raw_headers'] = tuple((k.encode('utf-8'), v.encode('utf-8')) - for k, v in headers.items()) - - message = self._message._replace(**dct) - - kwargs = {} - if scheme is not sentinel: - kwargs['scheme'] = scheme - if host is not sentinel: - kwargs['host'] = host - if remote is not sentinel: - kwargs['remote'] = remote - - return self.__class__( - message, - self._payload, - self._protocol, - self._payload_writer, - self._task, - self._loop, - client_max_size=self._client_max_size, - state=self._state.copy(), - **kwargs) - - @property - def task(self) -> 'asyncio.Task[None]': - return self._task - - @property - def protocol(self) -> 'RequestHandler': - return self._protocol - - @property - def transport(self) -> Optional[asyncio.Transport]: - if self._protocol is None: - return None - return self._protocol.transport - - @property - def writer(self) -> AbstractStreamWriter: - return self._payload_writer - - @reify - def message(self) -> RawRequestMessage: - warnings.warn("Request.message is deprecated", - DeprecationWarning, - stacklevel=3) - return self._message - - @reify - def rel_url(self) -> URL: - return self._rel_url - - @reify - def loop(self) -> asyncio.AbstractEventLoop: - warnings.warn("request.loop property is deprecated", - DeprecationWarning, - stacklevel=2) - return self._loop - - # MutableMapping API - - def __getitem__(self, key: str) -> Any: - return self._state[key] - - def __setitem__(self, key: str, value: Any) -> None: - self._state[key] = value - - def __delitem__(self, key: str) -> None: - del self._state[key] - - def __len__(self) -> int: - return len(self._state) - - def __iter__(self) -> Iterator[str]: - return iter(self._state) - - ######## - - @reify - def secure(self) -> bool: - """A bool indicating if the request is handled with SSL.""" - return self.scheme == 'https' - - @reify - def forwarded(self) -> Tuple[Mapping[str, str], ...]: - """A tuple containing all parsed Forwarded header(s). - - Makes an effort to parse Forwarded headers as specified by RFC 7239: - - - It adds one (immutable) dictionary per Forwarded 'field-value', ie - per proxy. The element corresponds to the data in the Forwarded - field-value added by the first proxy encountered by the client. Each - subsequent item corresponds to those added by later proxies. - - It checks that every value has valid syntax in general as specified - in section 4: either a 'token' or a 'quoted-string'. - - It un-escapes found escape sequences. - - It does NOT validate 'by' and 'for' contents as specified in section - 6. - - It does NOT validate 'host' contents (Host ABNF). - - It does NOT validate 'proto' contents for valid URI scheme names. - - Returns a tuple containing one or more immutable dicts - """ - elems = [] - for field_value in self._message.headers.getall(hdrs.FORWARDED, ()): - length = len(field_value) - pos = 0 - need_separator = False - elem = {} # type: Dict[str, str] - elems.append(types.MappingProxyType(elem)) - while 0 <= pos < length: - match = _FORWARDED_PAIR_RE.match(field_value, pos) - if match is not None: # got a valid forwarded-pair - if need_separator: - # bad syntax here, skip to next comma - pos = field_value.find(',', pos) - else: - name, value, port = match.groups() - if value[0] == '"': - # quoted string: remove quotes and unescape - value = _QUOTED_PAIR_REPLACE_RE.sub(r'\1', - value[1:-1]) - if port: - value += port - elem[name.lower()] = value - pos += len(match.group(0)) - need_separator = True - elif field_value[pos] == ',': # next forwarded-element - need_separator = False - elem = {} - elems.append(types.MappingProxyType(elem)) - pos += 1 - elif field_value[pos] == ';': # next forwarded-pair - need_separator = False - pos += 1 - elif field_value[pos] in ' \t': - # Allow whitespace even between forwarded-pairs, though - # RFC 7239 doesn't. This simplifies code and is in line - # with Postel's law. - pos += 1 - else: - # bad syntax here, skip to next comma - pos = field_value.find(',', pos) - return tuple(elems) - - @reify - def scheme(self) -> str: - """A string representing the scheme of the request. - - Hostname is resolved in this order: - - - overridden value by .clone(scheme=new_scheme) call. - - type of connection to peer: HTTPS if socket is SSL, HTTP otherwise. - - 'http' or 'https'. - """ - if self._transport_sslcontext: - return 'https' - else: - return 'http' - - @reify - def method(self) -> str: - """Read only property for getting HTTP method. - - The value is upper-cased str like 'GET', 'POST', 'PUT' etc. - """ - return self._method - - @reify - def version(self) -> Tuple[int, int]: - """Read only property for getting HTTP version of request. - - Returns aiohttp.protocol.HttpVersion instance. - """ - return self._version - - @reify - def host(self) -> str: - """Hostname of the request. - - Hostname is resolved in this order: - - - overridden value by .clone(host=new_host) call. - - HOST HTTP header - - socket.getfqdn() value - """ - host = self._message.headers.get(hdrs.HOST) - if host is not None: - return host - else: - return socket.getfqdn() - - @reify - def remote(self) -> Optional[str]: - """Remote IP of client initiated HTTP request. - - The IP is resolved in this order: - - - overridden value by .clone(remote=new_remote) call. - - peername of opened socket - """ - if isinstance(self._transport_peername, (list, tuple)): - return self._transport_peername[0] - else: - return self._transport_peername - - @reify - def url(self) -> URL: - url = URL.build(scheme=self.scheme, host=self.host) - return url.join(self._rel_url) - - @reify - def path(self) -> str: - """The URL including *PATH INFO* without the host or scheme. - - E.g., ``/app/blog`` - """ - return self._rel_url.path - - @reify - def path_qs(self) -> str: - """The URL including PATH_INFO and the query string. - - E.g, /app/blog?id=10 - """ - return str(self._rel_url) - - @reify - def raw_path(self) -> str: - """ The URL including raw *PATH INFO* without the host or scheme. - Warning, the path is unquoted and may contains non valid URL characters - - E.g., ``/my%2Fpath%7Cwith%21some%25strange%24characters`` - """ - return self._message.path - - @reify - def query(self) -> 'MultiDictProxy[str]': - """A multidict with all the variables in the query string.""" - return self._rel_url.query - - @reify - def query_string(self) -> str: - """The query string in the URL. - - E.g., id=10 - """ - return self._rel_url.query_string - - @reify - def headers(self) -> 'CIMultiDictProxy[str]': - """A case-insensitive multidict proxy with all headers.""" - return self._headers - - @reify - def raw_headers(self) -> RawHeaders: - """A sequence of pairs for all headers.""" - return self._message.raw_headers - - @staticmethod - def _http_date(_date_str: str) -> Optional[datetime.datetime]: - """Process a date string, return a datetime object - """ - if _date_str is not None: - timetuple = parsedate(_date_str) - if timetuple is not None: - return datetime.datetime(*timetuple[:6], - tzinfo=datetime.timezone.utc) - return None - - @reify - def if_modified_since(self) -> Optional[datetime.datetime]: - """The value of If-Modified-Since HTTP header, or None. - - This header is represented as a `datetime` object. - """ - return self._http_date(self.headers.get(hdrs.IF_MODIFIED_SINCE)) - - @reify - def if_unmodified_since(self) -> Optional[datetime.datetime]: - """The value of If-Unmodified-Since HTTP header, or None. - - This header is represented as a `datetime` object. - """ - return self._http_date(self.headers.get(hdrs.IF_UNMODIFIED_SINCE)) - - @reify - def if_range(self) -> Optional[datetime.datetime]: - """The value of If-Range HTTP header, or None. - - This header is represented as a `datetime` object. - """ - return self._http_date(self.headers.get(hdrs.IF_RANGE)) - - @reify - def keep_alive(self) -> bool: - """Is keepalive enabled by client?""" - return not self._message.should_close - - @reify - def cookies(self) -> Mapping[str, str]: - """Return request cookies. - - A read-only dictionary-like object. - """ - raw = self.headers.get(hdrs.COOKIE, '') - parsed = SimpleCookie(raw) - return MappingProxyType( - {key: val.value for key, val in parsed.items()}) - - @reify - def http_range(self) -> slice: - """The content of Range HTTP header. - - Return a slice instance. - - """ - rng = self._headers.get(hdrs.RANGE) - start, end = None, None - if rng is not None: - try: - pattern = r'^bytes=(\d*)-(\d*)$' - start, end = re.findall(pattern, rng)[0] - except IndexError: # pattern was not found in header - raise ValueError("range not in acceptable format") - - end = int(end) if end else None - start = int(start) if start else None - - if start is None and end is not None: - # end with no start is to return tail of content - start = -end - end = None - - if start is not None and end is not None: - # end is inclusive in range header, exclusive for slice - end += 1 - - if start >= end: - raise ValueError('start cannot be after end') - - if start is end is None: # No valid range supplied - raise ValueError('No start or end of range specified') - - return slice(start, end, 1) - - @reify - def content(self) -> StreamReader: - """Return raw payload stream.""" - return self._payload - - @property - def has_body(self) -> bool: - """Return True if request's HTTP BODY can be read, False otherwise.""" - warnings.warn( - "Deprecated, use .can_read_body #2005", - DeprecationWarning, stacklevel=2) - return not self._payload.at_eof() - - @property - def can_read_body(self) -> bool: - """Return True if request's HTTP BODY can be read, False otherwise.""" - return not self._payload.at_eof() - - @reify - def body_exists(self) -> bool: - """Return True if request has HTTP BODY, False otherwise.""" - return type(self._payload) is not EmptyStreamReader - - async def release(self) -> None: - """Release request. - - Eat unread part of HTTP BODY if present. - """ - while not self._payload.at_eof(): - await self._payload.readany() - - async def read(self) -> bytes: - """Read request body if present. - - Returns bytes object with full request content. - """ - if self._read_bytes is None: - body = bytearray() - while True: - chunk = await self._payload.readany() - body.extend(chunk) - if self._client_max_size: - body_size = len(body) - if body_size >= self._client_max_size: - raise HTTPRequestEntityTooLarge( - max_size=self._client_max_size, - actual_size=body_size - ) - if not chunk: - break - self._read_bytes = bytes(body) - return self._read_bytes - - async def text(self) -> str: - """Return BODY as text using encoding from .charset.""" - bytes_body = await self.read() - encoding = self.charset or 'utf-8' - return bytes_body.decode(encoding) - - async def json(self, *, loads: JSONDecoder=DEFAULT_JSON_DECODER) -> Any: - """Return BODY as JSON.""" - body = await self.text() - return loads(body) - - async def multipart(self) -> MultipartReader: - """Return async iterator to process BODY as multipart.""" - return MultipartReader(self._headers, self._payload) - - async def post(self) -> 'MultiDictProxy[Union[str, bytes, FileField]]': - """Return POST parameters.""" - if self._post is not None: - return self._post - if self._method not in self.POST_METHODS: - self._post = MultiDictProxy(MultiDict()) - return self._post - - content_type = self.content_type - if (content_type not in ('', - 'application/x-www-form-urlencoded', - 'multipart/form-data')): - self._post = MultiDictProxy(MultiDict()) - return self._post - - out = MultiDict() # type: MultiDict[Union[str, bytes, FileField]] - - if content_type == 'multipart/form-data': - multipart = await self.multipart() - max_size = self._client_max_size - - field = await multipart.next() - while field is not None: - size = 0 - field_ct = field.headers.get(hdrs.CONTENT_TYPE) - - if isinstance(field, BodyPartReader): - if field.filename and field_ct: - # store file in temp file - tmp = tempfile.TemporaryFile() - chunk = await field.read_chunk(size=2**16) - while chunk: - chunk = field.decode(chunk) - tmp.write(chunk) - size += len(chunk) - if 0 < max_size < size: - raise HTTPRequestEntityTooLarge( - max_size=max_size, - actual_size=size - ) - chunk = await field.read_chunk(size=2**16) - tmp.seek(0) - - ff = FileField(field.name, field.filename, - cast(io.BufferedReader, tmp), - field_ct, field.headers) - out.add(field.name, ff) - else: - # deal with ordinary data - value = await field.read(decode=True) - if field_ct is None or \ - field_ct.startswith('text/'): - charset = field.get_charset(default='utf-8') - out.add(field.name, value.decode(charset)) - else: - out.add(field.name, value) - size += len(value) - if 0 < max_size < size: - raise HTTPRequestEntityTooLarge( - max_size=max_size, - actual_size=size - ) - else: - raise ValueError( - 'To decode nested multipart you need ' - 'to use custom reader', - ) - - field = await multipart.next() - else: - data = await self.read() - if data: - charset = self.charset or 'utf-8' - out.extend( - parse_qsl( - data.rstrip().decode(charset), - keep_blank_values=True, - encoding=charset)) - - self._post = MultiDictProxy(out) - return self._post - - def __repr__(self) -> str: - ascii_encodable_path = self.path.encode('ascii', 'backslashreplace') \ - .decode('ascii') - return "<{} {} {} >".format(self.__class__.__name__, - self._method, ascii_encodable_path) - - def __eq__(self, other: object) -> bool: - return id(self) == id(other) - - def __bool__(self) -> bool: - return True - - async def _prepare_hook(self, response: StreamResponse) -> None: - return - - -class Request(BaseRequest): - - ATTRS = BaseRequest.ATTRS | frozenset(['_match_info']) - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - - # matchdict, route_name, handler - # or information about traversal lookup - - # initialized after route resolving - self._match_info = None # type: Optional[UrlMappingMatchInfo] - - if DEBUG: - def __setattr__(self, name: str, val: Any) -> None: - if name not in self.ATTRS: - warnings.warn("Setting custom {}.{} attribute " - "is discouraged".format(self.__class__.__name__, - name), - DeprecationWarning, - stacklevel=2) - super().__setattr__(name, val) - - def clone(self, *, method: str=sentinel, rel_url: - StrOrURL=sentinel, headers: LooseHeaders=sentinel, - scheme: str=sentinel, host: str=sentinel, remote: - str=sentinel) -> 'Request': - ret = super().clone(method=method, - rel_url=rel_url, - headers=headers, - scheme=scheme, - host=host, - remote=remote) - new_ret = cast(Request, ret) - new_ret._match_info = self._match_info - return new_ret - - @reify - def match_info(self) -> 'UrlMappingMatchInfo': - """Result of route resolving.""" - match_info = self._match_info - assert match_info is not None - return match_info - - @property - def app(self) -> 'Application': - """Application instance.""" - match_info = self._match_info - assert match_info is not None - return match_info.current_app - - @property - def config_dict(self) -> ChainMapProxy: - match_info = self._match_info - assert match_info is not None - lst = match_info.apps - app = self.app - idx = lst.index(app) - sublist = list(reversed(lst[:idx + 1])) - return ChainMapProxy(sublist) - - async def _prepare_hook(self, response: StreamResponse) -> None: - match_info = self._match_info - if match_info is None: - return - for app in match_info._apps: - await app.on_response_prepare.send(self, response) diff --git a/venv/Lib/site-packages/aiohttp/web_response.py b/venv/Lib/site-packages/aiohttp/web_response.py deleted file mode 100644 index fbe03cb2..00000000 --- a/venv/Lib/site-packages/aiohttp/web_response.py +++ /dev/null @@ -1,717 +0,0 @@ -import asyncio # noqa -import collections.abc # noqa -import datetime -import enum -import json -import math -import time -import warnings -import zlib -from concurrent.futures import Executor -from email.utils import parsedate -from http.cookies import SimpleCookie -from typing import ( # noqa - TYPE_CHECKING, - Any, - Dict, - Iterator, - Mapping, - MutableMapping, - Optional, - Tuple, - Union, - cast, -) - -from multidict import CIMultiDict, istr - -from . import hdrs, payload -from .abc import AbstractStreamWriter -from .helpers import HeadersMixin, rfc822_formatted_time, sentinel -from .http import RESPONSES, SERVER_SOFTWARE, HttpVersion10, HttpVersion11 -from .payload import Payload -from .typedefs import JSONEncoder, LooseHeaders - -__all__ = ('ContentCoding', 'StreamResponse', 'Response', 'json_response') - - -if TYPE_CHECKING: # pragma: no cover - from .web_request import BaseRequest # noqa - BaseClass = MutableMapping[str, Any] -else: - BaseClass = collections.abc.MutableMapping - - -class ContentCoding(enum.Enum): - # The content codings that we have support for. - # - # Additional registered codings are listed at: - # https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding - deflate = 'deflate' - gzip = 'gzip' - identity = 'identity' - - -############################################################ -# HTTP Response classes -############################################################ - - -class StreamResponse(BaseClass, HeadersMixin): - - _length_check = True - - def __init__(self, *, - status: int=200, - reason: Optional[str]=None, - headers: Optional[LooseHeaders]=None) -> None: - self._body = None - self._keep_alive = None # type: Optional[bool] - self._chunked = False - self._compression = False - self._compression_force = None # type: Optional[ContentCoding] - self._cookies = SimpleCookie() - - self._req = None # type: Optional[BaseRequest] - self._payload_writer = None # type: Optional[AbstractStreamWriter] - self._eof_sent = False - self._body_length = 0 - self._state = {} # type: Dict[str, Any] - - if headers is not None: - self._headers = CIMultiDict(headers) # type: CIMultiDict[str] - else: - self._headers = CIMultiDict() - - self.set_status(status, reason) - - @property - def prepared(self) -> bool: - return self._payload_writer is not None - - @property - def task(self) -> 'asyncio.Task[None]': - return getattr(self._req, 'task', None) - - @property - def status(self) -> int: - return self._status - - @property - def chunked(self) -> bool: - return self._chunked - - @property - def compression(self) -> bool: - return self._compression - - @property - def reason(self) -> str: - return self._reason - - def set_status(self, status: int, - reason: Optional[str]=None, - _RESPONSES: Mapping[int, - Tuple[str, str]]=RESPONSES) -> None: - assert not self.prepared, \ - 'Cannot change the response status code after ' \ - 'the headers have been sent' - self._status = int(status) - if reason is None: - try: - reason = _RESPONSES[self._status][0] - except Exception: - reason = '' - self._reason = reason - - @property - def keep_alive(self) -> Optional[bool]: - return self._keep_alive - - def force_close(self) -> None: - self._keep_alive = False - - @property - def body_length(self) -> int: - return self._body_length - - @property - def output_length(self) -> int: - warnings.warn('output_length is deprecated', DeprecationWarning) - assert self._payload_writer - return self._payload_writer.buffer_size - - def enable_chunked_encoding(self, chunk_size: Optional[int]=None) -> None: - """Enables automatic chunked transfer encoding.""" - self._chunked = True - - if hdrs.CONTENT_LENGTH in self._headers: - raise RuntimeError("You can't enable chunked encoding when " - "a content length is set") - if chunk_size is not None: - warnings.warn('Chunk size is deprecated #1615', DeprecationWarning) - - def enable_compression(self, - force: Optional[Union[bool, ContentCoding]]=None - ) -> None: - """Enables response compression encoding.""" - # Backwards compatibility for when force was a bool <0.17. - if type(force) == bool: - force = ContentCoding.deflate if force else ContentCoding.identity - warnings.warn("Using boolean for force is deprecated #3318", - DeprecationWarning) - elif force is not None: - assert isinstance(force, ContentCoding), ("force should one of " - "None, bool or " - "ContentEncoding") - - self._compression = True - self._compression_force = force - - @property - def headers(self) -> 'CIMultiDict[str]': - return self._headers - - @property - def cookies(self) -> SimpleCookie: - return self._cookies - - def set_cookie(self, name: str, value: str, *, - expires: Optional[str]=None, - domain: Optional[str]=None, - max_age: Optional[Union[int, str]]=None, - path: str='/', - secure: Optional[str]=None, - httponly: Optional[str]=None, - version: Optional[str]=None) -> None: - """Set or update response cookie. - - Sets new cookie or updates existent with new value. - Also updates only those params which are not None. - """ - - old = self._cookies.get(name) - if old is not None and old.coded_value == '': - # deleted cookie - self._cookies.pop(name, 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 - - if max_age is not None: - c['max-age'] = str(max_age) - elif 'max-age' in c: - del c['max-age'] - - c['path'] = path - - if secure is not None: - c['secure'] = secure - if httponly is not None: - c['httponly'] = httponly - if version is not None: - c['version'] = version - - def del_cookie(self, name: str, *, - domain: Optional[str]=None, - path: str='/') -> None: - """Delete cookie. - - Creates new empty expired cookie. - """ - # TODO: do we need domain/path here? - self._cookies.pop(name, None) - 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) -> Optional[int]: - # Just a placeholder for adding setter - return super().content_length - - @content_length.setter - def content_length(self, value: Optional[int]) -> None: - if value is not None: - value = int(value) - if self._chunked: - raise RuntimeError("You can't set content length when " - "chunked encoding is enable") - self._headers[hdrs.CONTENT_LENGTH] = str(value) - else: - self._headers.pop(hdrs.CONTENT_LENGTH, None) - - @property - def content_type(self) -> str: - # Just a placeholder for adding setter - return super().content_type - - @content_type.setter - def content_type(self, value: str) -> None: - self.content_type # read header values if needed - self._content_type = str(value) - self._generate_content_type_header() - - @property - def charset(self) -> Optional[str]: - # Just a placeholder for adding setter - return super().charset - - @charset.setter - def charset(self, value: Optional[str]) -> None: - ctype = self.content_type # read header values if needed - if ctype == 'application/octet-stream': - raise RuntimeError("Setting charset for application/octet-stream " - "doesn't make sense, setup content_type first") - assert self._content_dict is not None - if value is None: - self._content_dict.pop('charset', None) - else: - self._content_dict['charset'] = str(value).lower() - self._generate_content_type_header() - - @property - def last_modified(self) -> Optional[datetime.datetime]: - """The value of Last-Modified HTTP header, or None. - - This header is represented as a `datetime` object. - """ - httpdate = self._headers.get(hdrs.LAST_MODIFIED) - if httpdate is not None: - timetuple = parsedate(httpdate) - if timetuple is not None: - return datetime.datetime(*timetuple[:6], - tzinfo=datetime.timezone.utc) - return None - - @last_modified.setter - def last_modified(self, - value: Optional[ - Union[int, float, datetime.datetime, str]]) -> None: - if value is None: - self._headers.pop(hdrs.LAST_MODIFIED, None) - elif isinstance(value, (int, float)): - self._headers[hdrs.LAST_MODIFIED] = time.strftime( - "%a, %d %b %Y %H:%M:%S GMT", time.gmtime(math.ceil(value))) - elif isinstance(value, datetime.datetime): - self._headers[hdrs.LAST_MODIFIED] = time.strftime( - "%a, %d %b %Y %H:%M:%S GMT", value.utctimetuple()) - elif isinstance(value, str): - self._headers[hdrs.LAST_MODIFIED] = value - - def _generate_content_type_header( - self, - CONTENT_TYPE: istr=hdrs.CONTENT_TYPE) -> None: - assert self._content_dict is not None - assert self._content_type is not None - params = '; '.join("{}={}".format(k, v) - for k, v in self._content_dict.items()) - if params: - ctype = self._content_type + '; ' + params - else: - ctype = self._content_type - self._headers[CONTENT_TYPE] = ctype - - async def _do_start_compression(self, coding: ContentCoding) -> None: - if coding != ContentCoding.identity: - assert self._payload_writer is not None - self._headers[hdrs.CONTENT_ENCODING] = coding.value - self._payload_writer.enable_compression(coding.value) - # Compressed payload may have different content length, - # remove the header - self._headers.popall(hdrs.CONTENT_LENGTH, None) - - async def _start_compression(self, request: 'BaseRequest') -> None: - if self._compression_force: - await self._do_start_compression(self._compression_force) - else: - accept_encoding = request.headers.get( - hdrs.ACCEPT_ENCODING, '').lower() - for coding in ContentCoding: - if coding.value in accept_encoding: - await self._do_start_compression(coding) - return - - async def prepare( - self, - request: 'BaseRequest' - ) -> Optional[AbstractStreamWriter]: - if self._eof_sent: - return None - if self._payload_writer is not None: - return self._payload_writer - - await request._prepare_hook(self) - return await self._start(request) - - async def _start(self, request: 'BaseRequest') -> AbstractStreamWriter: - self._req = request - - keep_alive = self._keep_alive - if keep_alive is None: - keep_alive = request.keep_alive - self._keep_alive = keep_alive - - version = request.version - writer = self._payload_writer = request._payload_writer - - headers = self._headers - for cookie in self._cookies.values(): - value = cookie.output(header='')[1:] - headers.add(hdrs.SET_COOKIE, value) - - if self._compression: - await self._start_compression(request) - - if self._chunked: - if version != HttpVersion11: - raise RuntimeError( - "Using chunked encoding is forbidden " - "for HTTP/{0.major}.{0.minor}".format(request.version)) - writer.enable_chunking() - headers[hdrs.TRANSFER_ENCODING] = 'chunked' - if hdrs.CONTENT_LENGTH in headers: - del headers[hdrs.CONTENT_LENGTH] - elif self._length_check: - writer.length = self.content_length - if writer.length is None: - if version >= HttpVersion11: - writer.enable_chunking() - headers[hdrs.TRANSFER_ENCODING] = 'chunked' - if hdrs.CONTENT_LENGTH in headers: - del headers[hdrs.CONTENT_LENGTH] - else: - keep_alive = False - - headers.setdefault(hdrs.CONTENT_TYPE, 'application/octet-stream') - headers.setdefault(hdrs.DATE, rfc822_formatted_time()) - headers.setdefault(hdrs.SERVER, SERVER_SOFTWARE) - - # connection header - if hdrs.CONNECTION not in headers: - if keep_alive: - if version == HttpVersion10: - headers[hdrs.CONNECTION] = 'keep-alive' - else: - if version == HttpVersion11: - headers[hdrs.CONNECTION] = 'close' - - # status line - status_line = 'HTTP/{}.{} {} {}'.format( - version[0], version[1], self._status, self._reason) - await writer.write_headers(status_line, headers) - - return writer - - async def write(self, data: bytes) -> None: - assert isinstance(data, (bytes, bytearray, memoryview)), \ - "data argument must be byte-ish (%r)" % type(data) - - if self._eof_sent: - raise RuntimeError("Cannot call write() after write_eof()") - if self._payload_writer is None: - raise RuntimeError("Cannot call write() before prepare()") - - await self._payload_writer.write(data) - - async def drain(self) -> None: - assert not self._eof_sent, "EOF has already been sent" - assert self._payload_writer is not None, \ - "Response has not been started" - warnings.warn("drain method is deprecated, use await resp.write()", - DeprecationWarning, - stacklevel=2) - await self._payload_writer.drain() - - async def write_eof(self, data: bytes=b'') -> None: - assert isinstance(data, (bytes, bytearray, memoryview)), \ - "data argument must be byte-ish (%r)" % type(data) - - if self._eof_sent: - return - - assert self._payload_writer is not None, \ - "Response has not been started" - - await self._payload_writer.write_eof(data) - self._eof_sent = True - self._req = None - self._body_length = self._payload_writer.output_size - self._payload_writer = None - - def __repr__(self) -> str: - if self._eof_sent: - info = "eof" - elif self.prepared: - assert self._req is not None - info = "{} {} ".format(self._req.method, self._req.path) - else: - info = "not prepared" - return "<{} {} {}>".format(self.__class__.__name__, - self.reason, info) - - def __getitem__(self, key: str) -> Any: - return self._state[key] - - def __setitem__(self, key: str, value: Any) -> None: - self._state[key] = value - - def __delitem__(self, key: str) -> None: - del self._state[key] - - def __len__(self) -> int: - return len(self._state) - - def __iter__(self) -> Iterator[str]: - return iter(self._state) - - def __hash__(self) -> int: - return hash(id(self)) - - def __eq__(self, other: object) -> bool: - return self is other - - -class Response(StreamResponse): - - def __init__(self, *, - body: Any=None, - status: int=200, - reason: Optional[str]=None, - text: Optional[str]=None, - headers: Optional[LooseHeaders]=None, - content_type: Optional[str]=None, - charset: Optional[str]=None, - zlib_executor_size: Optional[int]=None, - zlib_executor: Executor=None) -> None: - if body is not None and text is not None: - raise ValueError("body and text are not allowed together") - - if headers is None: - real_headers = CIMultiDict() # type: CIMultiDict[str] - elif not isinstance(headers, CIMultiDict): - real_headers = CIMultiDict(headers) - else: - real_headers = headers # = cast('CIMultiDict[str]', headers) - - if content_type is not None and "charset" in content_type: - raise ValueError("charset must not be in content_type " - "argument") - - if text is not None: - if hdrs.CONTENT_TYPE in real_headers: - if content_type or charset: - raise ValueError("passing both Content-Type header and " - "content_type or charset params " - "is forbidden") - else: - # fast path for filling headers - if not isinstance(text, str): - raise TypeError("text argument must be str (%r)" % - type(text)) - if content_type is None: - content_type = 'text/plain' - if charset is None: - charset = 'utf-8' - real_headers[hdrs.CONTENT_TYPE] = ( - content_type + '; charset=' + charset) - body = text.encode(charset) - text = None - else: - if hdrs.CONTENT_TYPE in real_headers: - if content_type is not None or charset is not None: - raise ValueError("passing both Content-Type header and " - "content_type or charset params " - "is forbidden") - else: - if content_type is not None: - if charset is not None: - content_type += '; charset=' + charset - real_headers[hdrs.CONTENT_TYPE] = content_type - - super().__init__(status=status, reason=reason, headers=real_headers) - - if text is not None: - self.text = text - else: - self.body = body - - self._compressed_body = None # type: Optional[bytes] - self._zlib_executor_size = zlib_executor_size - self._zlib_executor = zlib_executor - - @property - def body(self) -> Optional[Union[bytes, Payload]]: - return self._body - - @body.setter - def body(self, body: bytes, - CONTENT_TYPE: istr=hdrs.CONTENT_TYPE, - CONTENT_LENGTH: istr=hdrs.CONTENT_LENGTH) -> None: - if body is None: - self._body = None # type: Optional[bytes] - self._body_payload = False # type: bool - elif isinstance(body, (bytes, bytearray)): - self._body = body - self._body_payload = False - else: - try: - self._body = body = payload.PAYLOAD_REGISTRY.get(body) - except payload.LookupError: - raise ValueError('Unsupported body type %r' % type(body)) - - self._body_payload = True - - headers = self._headers - - # set content-length header if needed - if not self._chunked and CONTENT_LENGTH not in headers: - size = body.size - if size is not None: - headers[CONTENT_LENGTH] = str(size) - - # set content-type - if CONTENT_TYPE not in headers: - headers[CONTENT_TYPE] = body.content_type - - # copy payload headers - if body.headers: - for (key, value) in body.headers.items(): - if key not in headers: - headers[key] = value - - self._compressed_body = None - - @property - def text(self) -> Optional[str]: - if self._body is None: - return None - return self._body.decode(self.charset or 'utf-8') - - @text.setter - def text(self, text: str) -> None: - assert text is None or isinstance(text, str), \ - "text argument must be str (%r)" % type(text) - - if self.content_type == 'application/octet-stream': - self.content_type = 'text/plain' - if self.charset is None: - self.charset = 'utf-8' - - self._body = text.encode(self.charset) - self._body_payload = False - self._compressed_body = None - - @property - def content_length(self) -> Optional[int]: - if self._chunked: - return None - - if hdrs.CONTENT_LENGTH in self._headers: - return super().content_length - - if self._compressed_body is not None: - # Return length of the compressed body - return len(self._compressed_body) - elif self._body_payload: - # A payload without content length, or a compressed payload - return None - elif self._body is not None: - return len(self._body) - else: - return 0 - - @content_length.setter - def content_length(self, value: Optional[int]) -> None: - raise RuntimeError("Content length is set automatically") - - async def write_eof(self, data: bytes=b'') -> None: - if self._eof_sent: - return - if self._compressed_body is None: - body = self._body # type: Optional[Union[bytes, Payload]] - else: - body = self._compressed_body - assert not data, "data arg is not supported, got {!r}".format(data) - assert self._req is not None - assert self._payload_writer is not None - if body is not None: - if (self._req._method == hdrs.METH_HEAD or - self._status in [204, 304]): - await super().write_eof() - elif self._body_payload: - payload = cast(Payload, body) - await payload.write(self._payload_writer) - await super().write_eof() - else: - await super().write_eof(cast(bytes, body)) - else: - await super().write_eof() - - async def _start(self, request: 'BaseRequest') -> AbstractStreamWriter: - if not self._chunked and hdrs.CONTENT_LENGTH not in self._headers: - if not self._body_payload: - if self._body is not None: - self._headers[hdrs.CONTENT_LENGTH] = str(len(self._body)) - else: - self._headers[hdrs.CONTENT_LENGTH] = '0' - - return await super()._start(request) - - def _compress_body(self, zlib_mode: int) -> None: - compressobj = zlib.compressobj(wbits=zlib_mode) - body_in = self._body - assert body_in is not None - self._compressed_body = \ - compressobj.compress(body_in) + compressobj.flush() - - async def _do_start_compression(self, coding: ContentCoding) -> None: - if self._body_payload or self._chunked: - return await super()._do_start_compression(coding) - - if coding != ContentCoding.identity: - # Instead of using _payload_writer.enable_compression, - # compress the whole body - zlib_mode = (16 + zlib.MAX_WBITS - if coding == ContentCoding.gzip else -zlib.MAX_WBITS) - body_in = self._body - assert body_in is not None - if self._zlib_executor_size is not None and \ - len(body_in) > self._zlib_executor_size: - await asyncio.get_event_loop().run_in_executor( - self._zlib_executor, self._compress_body, zlib_mode) - else: - self._compress_body(zlib_mode) - - body_out = self._compressed_body - assert body_out is not None - - self._headers[hdrs.CONTENT_ENCODING] = coding.value - self._headers[hdrs.CONTENT_LENGTH] = str(len(body_out)) - - -def json_response(data: Any=sentinel, *, - text: str=None, - body: bytes=None, - status: int=200, - reason: Optional[str]=None, - headers: LooseHeaders=None, - content_type: str='application/json', - dumps: JSONEncoder=json.dumps) -> Response: - if data is not sentinel: - if text or body: - raise ValueError( - "only one of data, text, or body should be specified" - ) - else: - text = dumps(data) - return Response(text=text, body=body, status=status, reason=reason, - headers=headers, content_type=content_type) diff --git a/venv/Lib/site-packages/aiohttp/web_routedef.py b/venv/Lib/site-packages/aiohttp/web_routedef.py deleted file mode 100644 index 91b5ef0f..00000000 --- a/venv/Lib/site-packages/aiohttp/web_routedef.py +++ /dev/null @@ -1,194 +0,0 @@ -import abc -import os # noqa -from typing import ( - TYPE_CHECKING, - Any, - Awaitable, - Callable, - Dict, - Iterator, - List, - Optional, - Sequence, - Type, - Union, - overload, -) - -import attr - -from . import hdrs -from .abc import AbstractView -from .typedefs import PathLike - -if TYPE_CHECKING: # pragma: no cover - from .web_urldispatcher import UrlDispatcher - from .web_request import Request - from .web_response import StreamResponse -else: - Request = StreamResponse = UrlDispatcher = None - - -__all__ = ('AbstractRouteDef', 'RouteDef', 'StaticDef', 'RouteTableDef', - 'head', 'options', 'get', 'post', 'patch', 'put', 'delete', - 'route', 'view', 'static') - - -class AbstractRouteDef(abc.ABC): - @abc.abstractmethod - def register(self, router: UrlDispatcher) -> None: - pass # pragma: no cover - - -_SimpleHandler = Callable[[Request], Awaitable[StreamResponse]] -_HandlerType = Union[Type[AbstractView], _SimpleHandler] - - -@attr.s(frozen=True, repr=False, slots=True) -class RouteDef(AbstractRouteDef): - method = attr.ib(type=str) - path = attr.ib(type=str) - handler = attr.ib() # type: _HandlerType - kwargs = attr.ib(type=Dict[str, Any]) - - def __repr__(self) -> str: - info = [] - for name, value in sorted(self.kwargs.items()): - info.append(", {}={!r}".format(name, value)) - return (" {handler.__name__!r}" - "{info}>".format(method=self.method, path=self.path, - handler=self.handler, info=''.join(info))) - - def register(self, router: UrlDispatcher) -> None: - if self.method in hdrs.METH_ALL: - reg = getattr(router, 'add_'+self.method.lower()) - reg(self.path, self.handler, **self.kwargs) - else: - router.add_route(self.method, self.path, self.handler, - **self.kwargs) - - -@attr.s(frozen=True, repr=False, slots=True) -class StaticDef(AbstractRouteDef): - prefix = attr.ib(type=str) - path = attr.ib() # type: PathLike - kwargs = attr.ib(type=Dict[str, Any]) - - def __repr__(self) -> str: - info = [] - for name, value in sorted(self.kwargs.items()): - info.append(", {}={!r}".format(name, value)) - return (" {path}" - "{info}>".format(prefix=self.prefix, path=self.path, - info=''.join(info))) - - def register(self, router: UrlDispatcher) -> None: - router.add_static(self.prefix, self.path, **self.kwargs) - - -def route(method: str, path: str, handler: _HandlerType, - **kwargs: Any) -> RouteDef: - return RouteDef(method, path, handler, kwargs) - - -def head(path: str, handler: _HandlerType, **kwargs: Any) -> RouteDef: - return route(hdrs.METH_HEAD, path, handler, **kwargs) - - -def options(path: str, handler: _HandlerType, **kwargs: Any) -> RouteDef: - return route(hdrs.METH_OPTIONS, path, handler, **kwargs) - - -def get(path: str, handler: _HandlerType, *, name: Optional[str]=None, - allow_head: bool=True, **kwargs: Any) -> RouteDef: - return route(hdrs.METH_GET, path, handler, name=name, - allow_head=allow_head, **kwargs) - - -def post(path: str, handler: _HandlerType, **kwargs: Any) -> RouteDef: - return route(hdrs.METH_POST, path, handler, **kwargs) - - -def put(path: str, handler: _HandlerType, **kwargs: Any) -> RouteDef: - return route(hdrs.METH_PUT, path, handler, **kwargs) - - -def patch(path: str, handler: _HandlerType, **kwargs: Any) -> RouteDef: - return route(hdrs.METH_PATCH, path, handler, **kwargs) - - -def delete(path: str, handler: _HandlerType, **kwargs: Any) -> RouteDef: - return route(hdrs.METH_DELETE, path, handler, **kwargs) - - -def view(path: str, handler: Type[AbstractView], **kwargs: Any) -> RouteDef: - return route(hdrs.METH_ANY, path, handler, **kwargs) - - -def static(prefix: str, path: PathLike, - **kwargs: Any) -> StaticDef: - return StaticDef(prefix, path, kwargs) - - -_Deco = Callable[[_HandlerType], _HandlerType] - - -class RouteTableDef(Sequence[AbstractRouteDef]): - """Route definition table""" - def __init__(self) -> None: - self._items = [] # type: List[AbstractRouteDef] - - def __repr__(self) -> str: - return "".format(len(self._items)) - - @overload - def __getitem__(self, index: int) -> AbstractRouteDef: ... # noqa - - @overload # noqa - def __getitem__(self, index: slice) -> List[AbstractRouteDef]: ... # noqa - - def __getitem__(self, index): # type: ignore # noqa - return self._items[index] - - def __iter__(self) -> Iterator[AbstractRouteDef]: - return iter(self._items) - - def __len__(self) -> int: - return len(self._items) - - def __contains__(self, item: object) -> bool: - return item in self._items - - def route(self, - method: str, - path: str, - **kwargs: Any) -> _Deco: - def inner(handler: _HandlerType) -> _HandlerType: - self._items.append(RouteDef(method, path, handler, kwargs)) - return handler - return inner - - def head(self, path: str, **kwargs: Any) -> _Deco: - return self.route(hdrs.METH_HEAD, path, **kwargs) - - def get(self, path: str, **kwargs: Any) -> _Deco: - return self.route(hdrs.METH_GET, path, **kwargs) - - def post(self, path: str, **kwargs: Any) -> _Deco: - return self.route(hdrs.METH_POST, path, **kwargs) - - def put(self, path: str, **kwargs: Any) -> _Deco: - return self.route(hdrs.METH_PUT, path, **kwargs) - - def patch(self, path: str, **kwargs: Any) -> _Deco: - return self.route(hdrs.METH_PATCH, path, **kwargs) - - def delete(self, path: str, **kwargs: Any) -> _Deco: - return self.route(hdrs.METH_DELETE, path, **kwargs) - - def view(self, path: str, **kwargs: Any) -> _Deco: - return self.route(hdrs.METH_ANY, path, **kwargs) - - def static(self, prefix: str, path: PathLike, - **kwargs: Any) -> None: - self._items.append(StaticDef(prefix, path, kwargs)) diff --git a/venv/Lib/site-packages/aiohttp/web_runner.py b/venv/Lib/site-packages/aiohttp/web_runner.py deleted file mode 100644 index e9bd2c44..00000000 --- a/venv/Lib/site-packages/aiohttp/web_runner.py +++ /dev/null @@ -1,337 +0,0 @@ -import asyncio -import signal -import socket -from abc import ABC, abstractmethod -from typing import Any, List, Optional, Set - -from yarl import URL - -from .web_app import Application -from .web_server import Server - -try: - from ssl import SSLContext -except ImportError: - SSLContext = object # type: ignore - - -__all__ = ('BaseSite', 'TCPSite', 'UnixSite', 'NamedPipeSite', 'SockSite', - 'BaseRunner', 'AppRunner', 'ServerRunner', 'GracefulExit') - - -class GracefulExit(SystemExit): - code = 1 - - -def _raise_graceful_exit() -> None: - raise GracefulExit() - - -class BaseSite(ABC): - __slots__ = ('_runner', '_shutdown_timeout', '_ssl_context', '_backlog', - '_server') - - def __init__(self, runner: 'BaseRunner', *, - shutdown_timeout: float=60.0, - ssl_context: Optional[SSLContext]=None, - backlog: int=128) -> None: - if runner.server is None: - raise RuntimeError("Call runner.setup() before making a site") - self._runner = runner - self._shutdown_timeout = shutdown_timeout - self._ssl_context = ssl_context - self._backlog = backlog - self._server = None # type: Optional[asyncio.AbstractServer] - - @property - @abstractmethod - def name(self) -> str: - pass # pragma: no cover - - @abstractmethod - async def start(self) -> None: - self._runner._reg_site(self) - - async def stop(self) -> None: - self._runner._check_site(self) - if self._server is None: - self._runner._unreg_site(self) - return # not started yet - self._server.close() - # named pipes do not have wait_closed property - if hasattr(self._server, 'wait_closed'): - await self._server.wait_closed() - await self._runner.shutdown() - assert self._runner.server - await self._runner.server.shutdown(self._shutdown_timeout) - self._runner._unreg_site(self) - - -class TCPSite(BaseSite): - __slots__ = ('_host', '_port', '_reuse_address', '_reuse_port') - - def __init__(self, runner: 'BaseRunner', - host: str=None, port: int=None, *, - shutdown_timeout: float=60.0, - ssl_context: Optional[SSLContext]=None, - backlog: int=128, reuse_address: Optional[bool]=None, - reuse_port: Optional[bool]=None) -> None: - super().__init__(runner, shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, backlog=backlog) - if host is None: - host = "0.0.0.0" - self._host = host - if port is None: - port = 8443 if self._ssl_context else 8080 - self._port = port - self._reuse_address = reuse_address - self._reuse_port = reuse_port - - @property - def name(self) -> str: - scheme = 'https' if self._ssl_context else 'http' - return str(URL.build(scheme=scheme, host=self._host, port=self._port)) - - async def start(self) -> None: - await super().start() - loop = asyncio.get_event_loop() - server = self._runner.server - assert server is not None - self._server = await loop.create_server( # type: ignore - server, self._host, self._port, - ssl=self._ssl_context, backlog=self._backlog, - reuse_address=self._reuse_address, - reuse_port=self._reuse_port) - - -class UnixSite(BaseSite): - __slots__ = ('_path', ) - - def __init__(self, runner: 'BaseRunner', path: str, *, - shutdown_timeout: float=60.0, - ssl_context: Optional[SSLContext]=None, - backlog: int=128) -> None: - super().__init__(runner, shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, backlog=backlog) - self._path = path - - @property - def name(self) -> str: - scheme = 'https' if self._ssl_context else 'http' - return '{}://unix:{}:'.format(scheme, self._path) - - async def start(self) -> None: - await super().start() - loop = asyncio.get_event_loop() - server = self._runner.server - assert server is not None - self._server = await loop.create_unix_server( - server, self._path, - ssl=self._ssl_context, backlog=self._backlog) - - -class NamedPipeSite(BaseSite): - __slots__ = ('_path', ) - - def __init__(self, runner: 'BaseRunner', path: str, *, - shutdown_timeout: float=60.0) -> None: - loop = asyncio.get_event_loop() - if not isinstance(loop, asyncio.ProactorEventLoop): # type: ignore - raise RuntimeError("Named Pipes only available in proactor" - "loop under windows") - super().__init__(runner, shutdown_timeout=shutdown_timeout) - self._path = path - - @property - def name(self) -> str: - return self._path - - async def start(self) -> None: - await super().start() - loop = asyncio.get_event_loop() - server = self._runner.server - assert server is not None - _server = await loop.start_serving_pipe( # type: ignore - server, self._path - ) - self._server = _server[0] - - -class SockSite(BaseSite): - __slots__ = ('_sock', '_name') - - def __init__(self, runner: 'BaseRunner', sock: socket.socket, *, - shutdown_timeout: float=60.0, - ssl_context: Optional[SSLContext]=None, - backlog: int=128) -> None: - super().__init__(runner, shutdown_timeout=shutdown_timeout, - ssl_context=ssl_context, backlog=backlog) - self._sock = sock - scheme = 'https' if self._ssl_context else 'http' - if hasattr(socket, 'AF_UNIX') and sock.family == socket.AF_UNIX: - name = '{}://unix:{}:'.format(scheme, sock.getsockname()) - else: - host, port = sock.getsockname()[:2] - name = str(URL.build(scheme=scheme, host=host, port=port)) - self._name = name - - @property - def name(self) -> str: - return self._name - - async def start(self) -> None: - await super().start() - loop = asyncio.get_event_loop() - server = self._runner.server - assert server is not None - self._server = await loop.create_server( # type: ignore - server, sock=self._sock, - ssl=self._ssl_context, backlog=self._backlog) - - -class BaseRunner(ABC): - __slots__ = ('_handle_signals', '_kwargs', '_server', '_sites') - - def __init__(self, *, handle_signals: bool=False, **kwargs: Any) -> None: - self._handle_signals = handle_signals - self._kwargs = kwargs - self._server = None # type: Optional[Server] - self._sites = [] # type: List[BaseSite] - - @property - def server(self) -> Optional[Server]: - return self._server - - @property - def addresses(self) -> List[str]: - ret = [] # type: List[str] - for site in self._sites: - server = site._server - if server is not None: - sockets = server.sockets - if sockets is not None: - for sock in sockets: - ret.append(sock.getsockname()) - return ret - - @property - def sites(self) -> Set[BaseSite]: - return set(self._sites) - - async def setup(self) -> None: - loop = asyncio.get_event_loop() - - if self._handle_signals: - try: - loop.add_signal_handler(signal.SIGINT, _raise_graceful_exit) - loop.add_signal_handler(signal.SIGTERM, _raise_graceful_exit) - except NotImplementedError: # pragma: no cover - # add_signal_handler is not implemented on Windows - pass - - self._server = await self._make_server() - - @abstractmethod - async def shutdown(self) -> None: - pass # pragma: no cover - - async def cleanup(self) -> None: - loop = asyncio.get_event_loop() - - if self._server is None: - # no started yet, do nothing - return - - # The loop over sites is intentional, an exception on gather() - # leaves self._sites in unpredictable state. - # The loop guaranties that a site is either deleted on success or - # still present on failure - for site in list(self._sites): - await site.stop() - await self._cleanup_server() - self._server = None - if self._handle_signals: - try: - loop.remove_signal_handler(signal.SIGINT) - loop.remove_signal_handler(signal.SIGTERM) - except NotImplementedError: # pragma: no cover - # remove_signal_handler is not implemented on Windows - pass - - @abstractmethod - async def _make_server(self) -> Server: - pass # pragma: no cover - - @abstractmethod - async def _cleanup_server(self) -> None: - pass # pragma: no cover - - def _reg_site(self, site: BaseSite) -> None: - if site in self._sites: - raise RuntimeError("Site {} is already registered in runner {}" - .format(site, self)) - self._sites.append(site) - - def _check_site(self, site: BaseSite) -> None: - if site not in self._sites: - raise RuntimeError("Site {} is not registered in runner {}" - .format(site, self)) - - def _unreg_site(self, site: BaseSite) -> None: - if site not in self._sites: - raise RuntimeError("Site {} is not registered in runner {}" - .format(site, self)) - self._sites.remove(site) - - -class ServerRunner(BaseRunner): - """Low-level web server runner""" - - __slots__ = ('_web_server',) - - def __init__(self, web_server: Server, *, - handle_signals: bool=False, **kwargs: Any) -> None: - super().__init__(handle_signals=handle_signals, **kwargs) - self._web_server = web_server - - async def shutdown(self) -> None: - pass - - async def _make_server(self) -> Server: - return self._web_server - - async def _cleanup_server(self) -> None: - pass - - -class AppRunner(BaseRunner): - """Web Application runner""" - - __slots__ = ('_app',) - - def __init__(self, app: Application, *, - handle_signals: bool=False, **kwargs: Any) -> None: - super().__init__(handle_signals=handle_signals, **kwargs) - if not isinstance(app, Application): - raise TypeError("The first argument should be web.Application " - "instance, got {!r}".format(app)) - self._app = app - - @property - def app(self) -> Application: - return self._app - - async def shutdown(self) -> None: - await self._app.shutdown() - - async def _make_server(self) -> Server: - loop = asyncio.get_event_loop() - self._app._set_loop(loop) - self._app.on_startup.freeze() - await self._app.startup() - self._app.freeze() - - return self._app._make_handler(loop=loop, **self._kwargs) - - async def _cleanup_server(self) -> None: - await self._app.cleanup() diff --git a/venv/Lib/site-packages/aiohttp/web_server.py b/venv/Lib/site-packages/aiohttp/web_server.py deleted file mode 100644 index ad746ed0..00000000 --- a/venv/Lib/site-packages/aiohttp/web_server.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Low level HTTP server.""" -import asyncio -from typing import Any, Awaitable, Callable, Dict, List, Optional # noqa - -from .abc import AbstractStreamWriter -from .helpers import get_running_loop -from .http_parser import RawRequestMessage -from .streams import StreamReader -from .web_protocol import RequestHandler, _RequestFactory, _RequestHandler -from .web_request import BaseRequest - -__all__ = ('Server',) - - -class Server: - - def __init__(self, - handler: _RequestHandler, - *, - request_factory: Optional[_RequestFactory]=None, - loop: Optional[asyncio.AbstractEventLoop]=None, - **kwargs: Any) -> None: - self._loop = get_running_loop(loop) - self._connections = {} # type: Dict[RequestHandler, asyncio.Transport] - self._kwargs = kwargs - self.requests_count = 0 - self.request_handler = handler - self.request_factory = request_factory or self._make_request - - @property - def connections(self) -> List[RequestHandler]: - return list(self._connections.keys()) - - def connection_made(self, handler: RequestHandler, - transport: asyncio.Transport) -> None: - self._connections[handler] = transport - - def connection_lost(self, handler: RequestHandler, - exc: Optional[BaseException]=None) -> None: - if handler in self._connections: - del self._connections[handler] - - def _make_request(self, message: RawRequestMessage, - payload: StreamReader, - protocol: RequestHandler, - writer: AbstractStreamWriter, - task: 'asyncio.Task[None]') -> BaseRequest: - return BaseRequest( - message, payload, protocol, writer, task, self._loop) - - async def shutdown(self, timeout: Optional[float]=None) -> None: - coros = [conn.shutdown(timeout) for conn in self._connections] - await asyncio.gather(*coros, loop=self._loop) - self._connections.clear() - - def __call__(self) -> RequestHandler: - return RequestHandler(self, loop=self._loop, **self._kwargs) diff --git a/venv/Lib/site-packages/aiohttp/web_urldispatcher.py b/venv/Lib/site-packages/aiohttp/web_urldispatcher.py index db3fb3a2..6625854e 100644 --- a/venv/Lib/site-packages/aiohttp/web_urldispatcher.py +++ b/venv/Lib/site-packages/aiohttp/web_urldispatcher.py @@ -1,135 +1,78 @@ import abc import asyncio -import base64 -import hashlib +import collections import inspect import keyword import os import re +import sys import warnings -from contextlib import contextmanager -from functools import wraps +from collections.abc import Container, Iterable, Sized from pathlib import Path from types import MappingProxyType -from typing import ( # noqa - TYPE_CHECKING, - Any, - Awaitable, - Callable, - Container, - Dict, - Generator, - Iterable, - Iterator, - List, - Mapping, - Optional, - Set, - Sized, - Tuple, - Type, - Union, - cast, -) - -from yarl import URL +from urllib.parse import unquote, urlencode from . import hdrs from .abc import AbstractMatchInfo, AbstractRouter, AbstractView -from .helpers import DEBUG -from .http import HttpVersion11 -from .typedefs import PathLike -from .web_exceptions import ( - HTTPException, - HTTPExpectationFailed, - HTTPForbidden, - HTTPMethodNotAllowed, - HTTPNotFound, -) -from .web_fileresponse import FileResponse -from .web_request import Request -from .web_response import Response, StreamResponse -from .web_routedef import AbstractRouteDef +from .file_sender import FileSender +from .protocol import HttpVersion11 +from .web_exceptions import (HTTPExpectationFailed, HTTPForbidden, + HTTPMethodNotAllowed, HTTPNotFound) +from .web_reqrep import Response, StreamResponse __all__ = ('UrlDispatcher', 'UrlMappingMatchInfo', 'AbstractResource', 'Resource', 'PlainResource', 'DynamicResource', + 'ResourceAdapter', 'AbstractRoute', 'ResourceRoute', - 'StaticResource', 'View') + 'Route', 'PlainRoute', 'DynamicRoute', 'StaticRoute', 'View') -if TYPE_CHECKING: # pragma: no cover - from .web_app import Application # noqa - BaseDict = Dict[str, str] -else: - BaseDict = dict - -HTTP_METHOD_RE = re.compile(r"^[0-9A-Za-z!#\$%&'\*\+\-\.\^_`\|~]+$") -ROUTE_RE = re.compile(r'(\{[_a-zA-Z][^{}]*(?:\{[^{}]*\}[^{}]*)*\})') -PATH_SEP = re.escape('/') +PY_35 = sys.version_info >= (3, 5) -_WebHandler = Callable[[Request], Awaitable[StreamResponse]] -_ExpectHandler = Callable[[Request], Awaitable[None]] -_Resolve = Tuple[Optional[AbstractMatchInfo], Set[str]] +HTTP_METHOD_RE = re.compile(r"^[0-9A-Za-z!#\$%&'\*\+\-\.\^_`\|~]+$") -class AbstractResource(Sized, Iterable['AbstractRoute']): +class AbstractResource(Sized, Iterable): - def __init__(self, *, name: Optional[str]=None) -> None: + def __init__(self, *, name=None): self._name = name @property - def name(self) -> Optional[str]: + def name(self): return self._name - @property - @abc.abstractmethod - def canonical(self) -> str: - """Exposes the resource's canonical path. - - For example '/foo/bar/{name}' - - """ - @abc.abstractmethod # pragma: no branch - def url_for(self, **kwargs: str) -> URL: + def url(self, **kwargs): """Construct url for resource with additional params.""" + @asyncio.coroutine @abc.abstractmethod # pragma: no branch - async def resolve(self, request: Request) -> _Resolve: + def resolve(self, method, path): """Resolve resource Return (UrlMappingMatchInfo, allowed_methods) pair.""" @abc.abstractmethod - def add_prefix(self, prefix: str) -> None: - """Add a prefix to processed URLs. - - Required for subapplications support. - - """ - - @abc.abstractmethod - def get_info(self) -> Dict[str, Any]: + def get_info(self): """Return a dict with additional info useful for introspection""" - def freeze(self) -> None: - pass - - @abc.abstractmethod - def raw_match(self, path: str) -> bool: - """Perform a raw match against path""" + @staticmethod + def _append_query(url, query): + if query: + return url + "?" + urlencode(query) + else: + return url class AbstractRoute(abc.ABC): - def __init__(self, method: str, - handler: Union[_WebHandler, Type[AbstractView]], *, - expect_handler: _ExpectHandler=None, - resource: AbstractResource=None) -> None: + def __init__(self, method, handler, *, + expect_handler=None, + resource=None): if expect_handler is None: - expect_handler = _default_expect_handler + expect_handler = _defaultExpectHandler assert asyncio.iscoroutinefunction(expect_handler), \ 'Coroutine is expected, got {!r}'.format(expect_handler) @@ -148,15 +91,12 @@ class AbstractRoute(abc.ABC): issubclass(handler, AbstractView)): pass else: - warnings.warn("Bare functions are deprecated, " - "use async ones", DeprecationWarning) - - @wraps(handler) - async def handler_wrapper(request: Request) -> StreamResponse: - result = old_handler(request) + @asyncio.coroutine + def handler_wrapper(*args, **kwargs): + result = old_handler(*args, **kwargs) if asyncio.iscoroutine(result): - return await result - return result # type: ignore + result = yield from result + return result old_handler = handler handler = handler_wrapper @@ -166,117 +106,81 @@ class AbstractRoute(abc.ABC): self._resource = resource @property - def method(self) -> str: + def method(self): return self._method @property - def handler(self) -> _WebHandler: + def handler(self): return self._handler @property @abc.abstractmethod - def name(self) -> Optional[str]: + def name(self): """Optional route's name, always equals to resource's name.""" @property - def resource(self) -> Optional[AbstractResource]: + def resource(self): return self._resource @abc.abstractmethod - def get_info(self) -> Dict[str, Any]: + def get_info(self): """Return a dict with additional info useful for introspection""" @abc.abstractmethod # pragma: no branch - def url_for(self, *args: str, **kwargs: str) -> URL: + def url(self, **kwargs): """Construct url for route with additional params.""" - async def handle_expect_header(self, request: Request) -> None: - await self._expect_handler(request) + @asyncio.coroutine + def handle_expect_header(self, request): + return (yield from self._expect_handler(request)) -class UrlMappingMatchInfo(BaseDict, AbstractMatchInfo): +class UrlMappingMatchInfo(dict, AbstractMatchInfo): - def __init__(self, match_dict: Dict[str, str], route: AbstractRoute): + def __init__(self, match_dict, route): super().__init__(match_dict) self._route = route - self._apps = [] # type: List[Application] - self._current_app = None # type: Optional[Application] - self._frozen = False @property - def handler(self) -> _WebHandler: + def handler(self): return self._route.handler @property - def route(self) -> AbstractRoute: + def route(self): return self._route @property - def expect_handler(self) -> _ExpectHandler: + def expect_handler(self): return self._route.handle_expect_header @property - def http_exception(self) -> Optional[HTTPException]: + def http_exception(self): return None - def get_info(self) -> Dict[str, str]: + def get_info(self): return self._route.get_info() - @property - def apps(self) -> Tuple['Application', ...]: - return tuple(self._apps) - - def add_app(self, app: 'Application') -> None: - if self._frozen: - raise RuntimeError("Cannot change apps stack after .freeze() call") - if self._current_app is None: - self._current_app = app - self._apps.insert(0, app) - - @property - def current_app(self) -> 'Application': - app = self._current_app - assert app is not None - return app - - @contextmanager - def set_current_app(self, - app: 'Application') -> Generator[None, None, None]: - if DEBUG: # pragma: no cover - if app not in self._apps: - raise RuntimeError( - "Expected one of the following apps {!r}, got {!r}" - .format(self._apps, app)) - prev = self._current_app - self._current_app = app - try: - yield - finally: - self._current_app = prev - - def freeze(self) -> None: - self._frozen = True - - def __repr__(self) -> str: + def __repr__(self): return "".format(super().__repr__(), self._route) class MatchInfoError(UrlMappingMatchInfo): - def __init__(self, http_exception: HTTPException) -> None: + def __init__(self, http_exception): self._exception = http_exception super().__init__({}, SystemRoute(self._exception)) @property - def http_exception(self) -> HTTPException: + def http_exception(self): return self._exception - def __repr__(self) -> str: + def __repr__(self): return "".format(self._exception.status, self._exception.reason) -async def _default_expect_handler(request: Request) -> None: +@asyncio.coroutine +def _defaultExpectHandler(request): """Default handler for Expect header. Just send "100 Continue" to client. @@ -285,224 +189,262 @@ async def _default_expect_handler(request: Request) -> None: expect = request.headers.get(hdrs.EXPECT) if request.version == HttpVersion11: if expect.lower() == "100-continue": - await request.writer.write(b"HTTP/1.1 100 Continue\r\n\r\n") + request.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n") else: raise HTTPExpectationFailed(text="Unknown Expect: %s" % expect) +class ResourceAdapter(AbstractResource): + + def __init__(self, route): + assert isinstance(route, Route), \ + 'Instance of Route class is required, got {!r}'.format(route) + super().__init__(name=route.name) + self._route = route + route._resource = self + + def url(self, **kwargs): + return self._route.url(**kwargs) + + @asyncio.coroutine + def resolve(self, method, path): + route_method = self._route.method + allowed_methods = set() + match_dict = self._route.match(path) + if match_dict is not None: + allowed_methods.add(route_method) + if route_method == hdrs.METH_ANY or route_method == method: + return (UrlMappingMatchInfo(match_dict, self._route), + allowed_methods) + return None, allowed_methods + + def get_info(self): + return self._route.get_info() + + def __len__(self): + return 1 + + def __iter__(self): + yield self._route + + class Resource(AbstractResource): - def __init__(self, *, name: Optional[str]=None) -> None: + def __init__(self, *, name=None): super().__init__(name=name) - self._routes = [] # type: List[ResourceRoute] + self._routes = [] - def add_route(self, method: str, - handler: Union[Type[AbstractView], _WebHandler], *, - expect_handler: Optional[_ExpectHandler]=None - ) -> 'ResourceRoute': + def add_route(self, method, handler, *, + expect_handler=None): - for route_obj in self._routes: - if route_obj.method == method or route_obj.method == hdrs.METH_ANY: + for route in self._routes: + if route.method == method or route.method == hdrs.METH_ANY: raise RuntimeError("Added route will never be executed, " - "method {route.method} is already " - "registered".format(route=route_obj)) + "method {route.method} is " + "already registered".format(route=route)) - route_obj = ResourceRoute(method, handler, self, - expect_handler=expect_handler) - self.register_route(route_obj) - return route_obj + route = ResourceRoute(method, handler, self, + expect_handler=expect_handler) + self.register_route(route) + return route - def register_route(self, route: 'ResourceRoute') -> None: + def register_route(self, route): assert isinstance(route, ResourceRoute), \ 'Instance of Route class is required, got {!r}'.format(route) self._routes.append(route) - async def resolve(self, request: Request) -> _Resolve: - allowed_methods = set() # type: Set[str] + @asyncio.coroutine + def resolve(self, method, path): + allowed_methods = set() - match_dict = self._match(request.rel_url.raw_path) + match_dict = self._match(path) if match_dict is None: return None, allowed_methods - for route_obj in self._routes: - route_method = route_obj.method + for route in self._routes: + route_method = route.method allowed_methods.add(route_method) - if (route_method == request.method or - route_method == hdrs.METH_ANY): - return (UrlMappingMatchInfo(match_dict, route_obj), - allowed_methods) + if route_method == method or route_method == hdrs.METH_ANY: + return UrlMappingMatchInfo(match_dict, route), allowed_methods else: return None, allowed_methods - @abc.abstractmethod - def _match(self, path: str) -> Optional[Dict[str, str]]: - pass # pragma: no cover - - def __len__(self) -> int: + def __len__(self): return len(self._routes) - def __iter__(self) -> Iterator[AbstractRoute]: + def __iter__(self): return iter(self._routes) - # TODO: implement all abstract methods - class PlainResource(Resource): - def __init__(self, path: str, *, name: Optional[str]=None) -> None: + def __init__(self, path, *, name=None): super().__init__(name=name) - assert not path or path.startswith('/') self._path = path - @property - def canonical(self) -> str: - return self._path - - def freeze(self) -> None: - if not self._path: - self._path = '/' - - def add_prefix(self, prefix: str) -> None: - assert prefix.startswith('/') - assert not prefix.endswith('/') - assert len(prefix) > 1 - self._path = prefix + self._path - - def _match(self, path: str) -> Optional[Dict[str, str]]: + def _match(self, path): # string comparison is about 10 times faster than regexp matching if self._path == path: return {} else: return None - def raw_match(self, path: str) -> bool: - return self._path == path - - def get_info(self) -> Dict[str, Any]: + def get_info(self): return {'path': self._path} - def url_for(self) -> URL: # type: ignore - return URL.build(path=self._path, encoded=True) + def url(self, *, query=None): + return self._append_query(self._path, query) - def __repr__(self) -> str: + def __repr__(self): name = "'" + self.name + "' " if self.name is not None else "" - return "".format(name=name, - path=self._path) + return "[_a-zA-Z][_a-zA-Z0-9]*)\}') - DYN_WITH_RE = re.compile( - r'\{(?P[_a-zA-Z][_a-zA-Z0-9]*):(?P.+)\}') - GOOD = r'[^{}/]+' - - def __init__(self, path: str, *, name: Optional[str]=None) -> None: + def __init__(self, pattern, formatter, *, name=None): super().__init__(name=name) - pattern = '' - formatter = '' - for part in ROUTE_RE.split(path): - match = self.DYN.fullmatch(part) - if match: - pattern += '(?P<{}>{})'.format(match.group('var'), self.GOOD) - formatter += '{' + match.group('var') + '}' - continue - - match = self.DYN_WITH_RE.fullmatch(part) - if match: - pattern += '(?P<{var}>{re})'.format(**match.groupdict()) - formatter += '{' + match.group('var') + '}' - continue - - if '{' in part or '}' in part: - raise ValueError("Invalid path '{}'['{}']".format(path, part)) - - path = URL.build(path=part).raw_path - formatter += path - pattern += re.escape(path) - - try: - compiled = re.compile(pattern) - except re.error as exc: - raise ValueError( - "Bad pattern '{}': {}".format(pattern, exc)) from None - assert compiled.pattern.startswith(PATH_SEP) - assert formatter.startswith('/') - self._pattern = compiled + self._pattern = pattern self._formatter = formatter - @property - def canonical(self) -> str: - return self._formatter - - def add_prefix(self, prefix: str) -> None: - assert prefix.startswith('/') - assert not prefix.endswith('/') - assert len(prefix) > 1 - self._pattern = re.compile(re.escape(prefix)+self._pattern.pattern) - self._formatter = prefix + self._formatter - - def _match(self, path: str) -> Optional[Dict[str, str]]: - match = self._pattern.fullmatch(path) + def _match(self, path): + match = self._pattern.match(path) if match is None: return None else: - return {key: URL.build(path=value, encoded=True).path - for key, value in match.groupdict().items()} + return {key: unquote(value) for key, value in + match.groupdict().items()} - def raw_match(self, path: str) -> bool: - return self._formatter == path - - def get_info(self) -> Dict[str, Any]: + def get_info(self): return {'formatter': self._formatter, 'pattern': self._pattern} - def url_for(self, **parts: str) -> URL: - url = self._formatter.format_map({k: URL.build(path=v).raw_path - for k, v in parts.items()}) - return URL.build(path=url) + def url(self, *, parts, query=None): + url = self._formatter.format_map(parts) + return self._append_query(url, query) - def __repr__(self) -> str: + def __repr__(self): name = "'" + self.name + "' " if self.name is not None else "" - return ("" + return (" None: - assert not prefix or prefix.startswith('/'), prefix - assert prefix in ('', '/') or not prefix.endswith('/'), prefix - super().__init__(name=name) - self._prefix = URL.build(path=prefix).raw_path + def __init__(self, method, handler, resource, *, + expect_handler=None): + super().__init__(method, handler, expect_handler=expect_handler, + resource=resource) + + def __repr__(self): + return " {handler!r}".format( + method=self.method, resource=self._resource, + handler=self.handler) @property - def canonical(self) -> str: - return self._prefix + def name(self): + return self._resource.name - def add_prefix(self, prefix: str) -> None: - assert prefix.startswith('/') - assert not prefix.endswith('/') - assert len(prefix) > 1 - self._prefix = prefix + self._prefix + def url(self, **kwargs): + """Construct url for route with additional params.""" + return self._resource.url(**kwargs) + + def get_info(self): + return self._resource.get_info() + + _append_query = staticmethod(Resource._append_query) + + +class Route(AbstractRoute): + """Old fashion route""" + + def __init__(self, method, handler, name, *, expect_handler=None): + super().__init__(method, handler, expect_handler=expect_handler) + self._name = name + + @property + def name(self): + return self._name + + @abc.abstractmethod + def match(self, path): + """Return dict with info for given path or + None if route cannot process path.""" + + _append_query = staticmethod(Resource._append_query) + + +class PlainRoute(Route): + + def __init__(self, method, handler, name, path, *, expect_handler=None): + super().__init__(method, handler, name, expect_handler=expect_handler) + self._path = path + + def match(self, path): + # string comparison is about 10 times faster than regexp matching + if self._path == path: + return {} + else: + return None + + def url(self, *, query=None): + return self._append_query(self._path, query) + + def get_info(self): + return {'path': self._path} + + def __repr__(self): + name = "'" + self.name + "' " if self.name is not None else "" + return " {handler!r}".format( + name=name, method=self.method, path=self._path, + handler=self.handler) + + +class DynamicRoute(Route): - def raw_match(self, prefix: str) -> bool: - return False + def __init__(self, method, handler, name, pattern, formatter, *, + expect_handler=None): + super().__init__(method, handler, name, expect_handler=expect_handler) + self._pattern = pattern + self._formatter = formatter - # TODO: impl missing abstract methods + def match(self, path): + match = self._pattern.match(path) + if match is None: + return None + else: + return match.groupdict() + def url(self, *, parts, query=None): + url = self._formatter.format_map(parts) + return self._append_query(url, query) -class StaticResource(PrefixResource): - VERSION_KEY = 'v' + def get_info(self): + return {'formatter': self._formatter, + 'pattern': self._pattern} - def __init__(self, prefix: str, directory: PathLike, - *, name: Optional[str]=None, - expect_handler: Optional[_ExpectHandler]=None, - chunk_size: int=256 * 1024, - show_index: bool=False, follow_symlinks: bool=False, - append_version: bool=False) -> None: - super().__init__(prefix, name=name) + def __repr__(self): + name = "'" + self.name + "' " if self.name is not None else "" + return (" {handler!r}" + .format(name=name, method=self.method, + formatter=self._formatter, handler=self.handler)) + + +class StaticRoute(Route): + + def __init__(self, name, prefix, directory, *, + expect_handler=None, chunk_size=256*1024, + response_factory=StreamResponse, + show_index=False): + assert prefix.startswith('/'), prefix + assert prefix.endswith('/'), prefix + super().__init__( + 'GET', self.handle, name, expect_handler=expect_handler) + self._prefix = prefix + self._prefix_len = len(self._prefix) try: directory = Path(directory) if str(directory).startswith('~'): @@ -514,144 +456,77 @@ class StaticResource(PrefixResource): raise ValueError( "No directory exists at '{}'".format(directory)) from error self._directory = directory + self._file_sender = FileSender(resp_factory=response_factory, + chunk_size=chunk_size) self._show_index = show_index - self._chunk_size = chunk_size - self._follow_symlinks = follow_symlinks - self._expect_handler = expect_handler - self._append_version = append_version - self._routes = {'GET': ResourceRoute('GET', self._handle, self, - expect_handler=expect_handler), - - 'HEAD': ResourceRoute('HEAD', self._handle, self, - expect_handler=expect_handler)} + def match(self, path): + if not path.startswith(self._prefix): + return None + return {'filename': path[self._prefix_len:]} - def url_for(self, *, filename: Union[str, Path], # type: ignore - append_version: Optional[bool]=None) -> URL: - if append_version is None: - append_version = self._append_version + def url(self, *, filename, query=None): if isinstance(filename, Path): filename = str(filename) while filename.startswith('/'): filename = filename[1:] - filename = '/' + filename - - # filename is not encoded - url = URL.build(path=self._prefix + filename) - - if append_version: - try: - if filename.startswith('/'): - filename = filename[1:] - filepath = self._directory.joinpath(filename).resolve() - if not self._follow_symlinks: - filepath.relative_to(self._directory) - except (ValueError, FileNotFoundError): - # ValueError for case when path point to symlink - # with follow_symlinks is False - return url # relatively safe - if filepath.is_file(): - # TODO cache file content - # with file watcher for cache invalidation - with open(str(filepath), mode='rb') as f: - file_bytes = f.read() - h = self._get_file_hash(file_bytes) - url = url.with_query({self.VERSION_KEY: h}) - return url - return url + url = self._prefix + filename + return self._append_query(url, query) - @staticmethod - def _get_file_hash(byte_array: bytes) -> str: - m = hashlib.sha256() # todo sha256 can be configurable param - m.update(byte_array) - b64 = base64.urlsafe_b64encode(m.digest()) - return b64.decode('ascii') - - def get_info(self) -> Dict[str, Any]: + def get_info(self): return {'directory': self._directory, 'prefix': self._prefix} - def set_options_route(self, handler: _WebHandler) -> None: - if 'OPTIONS' in self._routes: - raise RuntimeError('OPTIONS route was set already') - self._routes['OPTIONS'] = ResourceRoute( - 'OPTIONS', handler, self, - expect_handler=self._expect_handler) - - async def resolve(self, request: Request) -> _Resolve: - path = request.rel_url.raw_path - method = request.method - allowed_methods = set(self._routes) - if not path.startswith(self._prefix): - return None, set() - - if method not in allowed_methods: - return None, allowed_methods - - match_dict = {'filename': URL.build(path=path[len(self._prefix)+1:], - encoded=True).path} - return (UrlMappingMatchInfo(match_dict, self._routes[method]), - allowed_methods) - - def __len__(self) -> int: - return len(self._routes) - - def __iter__(self) -> Iterator[AbstractRoute]: - return iter(self._routes.values()) - - async def _handle(self, request: Request) -> StreamResponse: - rel_url = request.match_info['filename'] + @asyncio.coroutine + def handle(self, request): + filename = unquote(request.match_info['filename']) try: - filename = Path(rel_url) - if filename.anchor: - # rel_url is an absolute name like - # /static/\\machine_name\c$ or /static/D:\path - # where the static dir is totally different - raise HTTPForbidden() filepath = self._directory.joinpath(filename).resolve() - if not self._follow_symlinks: - filepath.relative_to(self._directory) + filepath.relative_to(self._directory) except (ValueError, FileNotFoundError) as error: # relatively safe raise HTTPNotFound() from error - except HTTPForbidden: - raise except Exception as error: # perm error or other kind! request.app.logger.exception(error) raise HTTPNotFound() from error - # on opening a dir, load its contents if allowed + # on opening a dir, load it's contents if allowed if filepath.is_dir(): if self._show_index: try: - return Response(text=self._directory_as_html(filepath), - content_type="text/html") + ret = Response(text=self._directory_as_html(filepath), + content_type="text/html") except PermissionError: raise HTTPForbidden() else: raise HTTPForbidden() elif filepath.is_file(): - return FileResponse(filepath, chunk_size=self._chunk_size) + ret = yield from self._file_sender.send(request, filepath) else: raise HTTPNotFound - def _directory_as_html(self, filepath: Path) -> str: - # returns directory's index as html + return ret + def _directory_as_html(self, filepath): + "returns directory's index as html" # sanity check assert filepath.is_dir() - relative_path_to_dir = filepath.relative_to(self._directory).as_posix() + posix_dir_len = len(self._directory.as_posix()) + + # remove the beginning of posix path, so it would be relative + # to our added static path + relative_path_to_dir = filepath.as_posix()[posix_dir_len:] index_of = "Index of /{}".format(relative_path_to_dir) + head = "\n{}\n".format(index_of) h1 = "

{}

".format(index_of) index_list = [] dir_index = filepath.iterdir() for _file in sorted(dir_index): # show file url as relative to static path - rel_path = _file.relative_to(self._directory).as_posix() - file_url = self._prefix + '/' + rel_path + file_url = _file.as_posix()[posix_dir_len:] # if file is a directory, add '/' to the end of the name if _file.is_dir(): @@ -666,291 +541,125 @@ class StaticResource(PrefixResource): ul = "
    \n{}\n
".format('\n'.join(index_list)) body = "\n{}\n{}\n".format(h1, ul) - head_str = "\n{}\n".format(index_of) - html = "\n{}\n{}\n".format(head_str, body) + html = "\n{}\n{}\n".format(head, body) return html - def __repr__(self) -> str: - name = "'" + self.name + "'" if self.name is not None else "" - return " {directory!r}>".format( - name=name, path=self._prefix, directory=self._directory) - - -class PrefixedSubAppResource(PrefixResource): - - def __init__(self, prefix: str, app: 'Application') -> None: - super().__init__(prefix) - self._app = app - for resource in app.router.resources(): - resource.add_prefix(prefix) - - def add_prefix(self, prefix: str) -> None: - super().add_prefix(prefix) - for resource in self._app.router.resources(): - resource.add_prefix(prefix) - - def url_for(self, *args: str, **kwargs: str) -> URL: - raise RuntimeError(".url_for() is not supported " - "by sub-application root") - - def get_info(self) -> Dict[str, Any]: - return {'app': self._app, - 'prefix': self._prefix} - - async def resolve(self, request: Request) -> _Resolve: - if not request.url.raw_path.startswith(self._prefix + '/') and \ - request.url.raw_path != self._prefix: - return None, set() - match_info = await self._app.router.resolve(request) - match_info.add_app(self._app) - if isinstance(match_info.http_exception, HTTPMethodNotAllowed): - methods = match_info.http_exception.allowed_methods - else: - methods = set() - return match_info, methods - - def __len__(self) -> int: - return len(self._app.router.routes()) - - def __iter__(self) -> Iterator[AbstractRoute]: - return iter(self._app.router.routes()) - - def __repr__(self) -> str: - return " {app!r}>".format( - prefix=self._prefix, app=self._app) - - -class AbstractRuleMatching(abc.ABC): - @abc.abstractmethod # pragma: no branch - async def match(self, request: Request) -> bool: - """Return bool if the request satisfies the criteria""" - - @abc.abstractmethod # pragma: no branch - def get_info(self) -> Dict[str, Any]: - """Return a dict with additional info useful for introspection""" - - @property - @abc.abstractmethod # pragma: no branch - def canonical(self) -> str: - """Return a str""" - - -class Domain(AbstractRuleMatching): - re_part = re.compile(r"(?!-)[a-z\d-]{1,63}(? None: - super().__init__() - self._domain = self.validation(domain) - - @property - def canonical(self) -> str: - return self._domain - - def validation(self, domain: str) -> str: - if not isinstance(domain, str): - raise TypeError("Domain must be str") - domain = domain.rstrip('.').lower() - if not domain: - raise ValueError("Domain cannot be empty") - elif '://' in domain: - raise ValueError("Scheme not supported") - url = URL('http://' + domain) - if not all( - self.re_part.fullmatch(x) - for x in url.raw_host.split(".")): # type: ignore - raise ValueError("Domain not valid") - if url.port == 80: - return url.raw_host # type: ignore - return '{}:{}'.format(url.raw_host, url.port) - - async def match(self, request: Request) -> bool: - host = request.headers.get(hdrs.HOST) - return host and self.match_domain(host) - - def match_domain(self, host: str) -> bool: - return host.lower() == self._domain - - def get_info(self) -> Dict[str, Any]: - return {'domain': self._domain} - - -class MaskDomain(Domain): - re_part = re.compile(r"(?!-)[a-z\d\*-]{1,63}(? None: - super().__init__(domain) - mask = self._domain.replace('.', r'\.').replace('*', '.*') - self._mask = re.compile(mask) - - @property - def canonical(self) -> str: - return self._mask.pattern - - def match_domain(self, host: str) -> bool: - return self._mask.fullmatch(host) is not None - - -class MatchedSubAppResource(PrefixedSubAppResource): - - def __init__(self, rule: AbstractRuleMatching, app: 'Application') -> None: - AbstractResource.__init__(self) - self._prefix = '' - self._app = app - self._rule = rule - - @property - def canonical(self) -> str: - return self._rule.canonical - - def get_info(self) -> Dict[str, Any]: - return {'app': self._app, - 'rule': self._rule} - - async def resolve(self, request: Request) -> _Resolve: - if not await self._rule.match(request): - return None, set() - match_info = await self._app.router.resolve(request) - match_info.add_app(self._app) - if isinstance(match_info.http_exception, HTTPMethodNotAllowed): - methods = match_info.http_exception.allowed_methods - else: - methods = set() - return match_info, methods - - def __repr__(self) -> str: - return " {app!r}>" \ - "".format(app=self._app) - - -class ResourceRoute(AbstractRoute): - """A route with resource""" - - def __init__(self, method: str, - handler: Union[_WebHandler, Type[AbstractView]], - resource: AbstractResource, *, - expect_handler: Optional[_ExpectHandler]=None) -> None: - super().__init__(method, handler, expect_handler=expect_handler, - resource=resource) - - def __repr__(self) -> str: - return " {handler!r}".format( - method=self.method, resource=self._resource, - handler=self.handler) - - @property - def name(self) -> Optional[str]: - return self._resource.name # type: ignore - - def url_for(self, *args: str, **kwargs: str) -> URL: - """Construct url for route with additional params.""" - return self._resource.url_for(*args, **kwargs) # type: ignore - - def get_info(self) -> Dict[str, Any]: - return self._resource.get_info() # type: ignore + def __repr__(self): + name = "'" + self.name + "' " if self.name is not None else "" + return " {directory!r}".format( + name=name, method=self.method, path=self._prefix, + directory=self._directory) -class SystemRoute(AbstractRoute): +class SystemRoute(Route): - def __init__(self, http_exception: HTTPException) -> None: - super().__init__(hdrs.METH_ANY, self._handle) + def __init__(self, http_exception): + super().__init__(hdrs.METH_ANY, self._handler, None) self._http_exception = http_exception - def url_for(self, *args: str, **kwargs: str) -> URL: - raise RuntimeError(".url_for() is not allowed for SystemRoute") + def url(self, **kwargs): + raise RuntimeError(".url() is not allowed for SystemRoute") - @property - def name(self) -> Optional[str]: + def match(self, path): return None - def get_info(self) -> Dict[str, Any]: + def get_info(self): return {'http_exception': self._http_exception} - async def _handle(self, request: Request) -> StreamResponse: + @asyncio.coroutine + def _handler(self, request): raise self._http_exception @property - def status(self) -> int: + def status(self): return self._http_exception.status @property - def reason(self) -> str: + def reason(self): return self._http_exception.reason - def __repr__(self) -> str: + def __repr__(self): return "".format(self=self) class View(AbstractView): - async def _iter(self) -> StreamResponse: + @asyncio.coroutine + def __iter__(self): if self.request.method not in hdrs.METH_ALL: self._raise_allowed_methods() method = getattr(self, self.request.method.lower(), None) if method is None: self._raise_allowed_methods() - resp = await method() + resp = yield from method() return resp - def __await__(self) -> Generator[Any, None, StreamResponse]: - return self._iter().__await__() + if PY_35: + def __await__(self): + return (yield from self.__iter__()) - def _raise_allowed_methods(self) -> None: + def _raise_allowed_methods(self): allowed_methods = { m for m in hdrs.METH_ALL if hasattr(self, m.lower())} raise HTTPMethodNotAllowed(self.request.method, allowed_methods) -class ResourcesView(Sized, - Iterable[AbstractResource], - Container[AbstractResource]): +class ResourcesView(Sized, Iterable, Container): - def __init__(self, resources: List[AbstractResource]) -> None: + def __init__(self, resources): self._resources = resources - def __len__(self) -> int: + def __len__(self): return len(self._resources) - def __iter__(self) -> Iterator[AbstractResource]: + def __iter__(self): yield from self._resources - def __contains__(self, resource: object) -> bool: + def __contains__(self, resource): return resource in self._resources -class RoutesView(Sized, Iterable[AbstractRoute], Container[AbstractRoute]): +class RoutesView(Sized, Iterable, Container): - def __init__(self, resources: List[AbstractResource]): - self._routes = [] # type: List[AbstractRoute] + def __init__(self, resources): + self._routes = [] for resource in resources: for route in resource: self._routes.append(route) - def __len__(self) -> int: + def __len__(self): return len(self._routes) - def __iter__(self) -> Iterator[AbstractRoute]: + def __iter__(self): yield from self._routes - def __contains__(self, route: object) -> bool: + def __contains__(self, route): return route in self._routes -class UrlDispatcher(AbstractRouter, Mapping[str, AbstractResource]): +class UrlDispatcher(AbstractRouter, collections.abc.Mapping): - NAME_SPLIT_RE = re.compile(r'[.:-]') + DYN = re.compile(r'^\{(?P[a-zA-Z][_a-zA-Z0-9]*)\}$') + DYN_WITH_RE = re.compile( + r'^\{(?P[a-zA-Z][_a-zA-Z0-9]*):(?P.+)\}$') + GOOD = r'[^{}/]+' + ROUTE_RE = re.compile(r'(\{[_a-zA-Z][^{}]*(?:\{[^{}]*\}[^{}]*)*\})') + NAME_SPLIT_RE = re.compile('[.:-]') - def __init__(self) -> None: + def __init__(self): super().__init__() - self._resources = [] # type: List[AbstractResource] - self._named_resources = {} # type: Dict[str, AbstractResource] + self._resources = [] + self._named_resources = {} - async def resolve(self, request: Request) -> AbstractMatchInfo: + @asyncio.coroutine + def resolve(self, request): + path = request.raw_path method = request.method - allowed_methods = set() # type: Set[str] + allowed_methods = set() for resource in self._resources: - match_dict, allowed = await resource.resolve(request) + match_dict, allowed = yield from resource.resolve(method, path) if match_dict is not None: return match_dict else: @@ -962,34 +671,41 @@ class UrlDispatcher(AbstractRouter, Mapping[str, AbstractResource]): else: return MatchInfoError(HTTPNotFound()) - def __iter__(self) -> Iterator[str]: + def __iter__(self): return iter(self._named_resources) - def __len__(self) -> int: + def __len__(self): return len(self._named_resources) - def __contains__(self, resource: object) -> bool: - return resource in self._named_resources + def __contains__(self, name): + return name in self._named_resources - def __getitem__(self, name: str) -> AbstractResource: + def __getitem__(self, name): return self._named_resources[name] - def resources(self) -> ResourcesView: + def resources(self): return ResourcesView(self._resources) - def routes(self) -> RoutesView: + def routes(self): return RoutesView(self._resources) - def named_resources(self) -> Mapping[str, AbstractResource]: + def named_resources(self): return MappingProxyType(self._named_resources) - def register_resource(self, resource: AbstractResource) -> None: + def named_routes(self): + # NB: it's ambiguous but it's really resources. + warnings.warn("Use .named_resources instead", DeprecationWarning) + return self.named_resources() + + def register_route(self, route): + warnings.warn("Use resource-based interface", DeprecationWarning) + resource = ResourceAdapter(route) + self._reg_resource(resource) + + def _reg_resource(self, resource): assert isinstance(resource, AbstractResource), \ 'Instance of AbstractResource class is required, got {!r}'.format( resource) - if self.frozen: - raise RuntimeError( - "Cannot register a resource into frozen router.") name = resource.name @@ -1008,39 +724,53 @@ class UrlDispatcher(AbstractRouter, Mapping[str, AbstractResource]): self._named_resources[name] = resource self._resources.append(resource) - def add_resource(self, path: str, *, - name: Optional[str]=None) -> Resource: - if path and not path.startswith('/'): - raise ValueError("path should be started with / or be empty") - # Reuse last added resource if path and name are the same - if self._resources: - resource = self._resources[-1] - if resource.name == name and resource.raw_match(path): - return cast(Resource, resource) - if not ('{' in path or '}' in path or ROUTE_RE.search(path)): - url = URL.build(path=path) - resource = PlainResource(url.raw_path, name=name) - self.register_resource(resource) + def add_resource(self, path, *, name=None): + if not path.startswith('/'): + raise ValueError("path should be started with /") + if not ('{' in path or '}' in path or self.ROUTE_RE.search(path)): + resource = PlainResource(path, name=name) + self._reg_resource(resource) return resource - resource = DynamicResource(path, name=name) - self.register_resource(resource) + + pattern = '' + formatter = '' + for part in self.ROUTE_RE.split(path): + match = self.DYN.match(part) + if match: + pattern += '(?P<{}>{})'.format(match.group('var'), self.GOOD) + formatter += '{' + match.group('var') + '}' + continue + + match = self.DYN_WITH_RE.match(part) + if match: + pattern += '(?P<{var}>{re})'.format(**match.groupdict()) + formatter += '{' + match.group('var') + '}' + continue + + if '{' in part or '}' in part: + raise ValueError("Invalid path '{}'['{}']".format(path, part)) + + formatter += part + pattern += re.escape(part) + + try: + compiled = re.compile('^' + pattern + '$') + except re.error as exc: + raise ValueError( + "Bad pattern '{}': {}".format(pattern, exc)) from None + resource = DynamicResource(compiled, formatter, name=name) + self._reg_resource(resource) return resource - def add_route(self, method: str, path: str, - handler: Union[_WebHandler, Type[AbstractView]], - *, name: Optional[str]=None, - expect_handler: Optional[_ExpectHandler]=None - ) -> AbstractRoute: + def add_route(self, method, path, handler, + *, name=None, expect_handler=None): resource = self.add_resource(path, name=name) return resource.add_route(method, handler, expect_handler=expect_handler) - def add_static(self, prefix: str, path: PathLike, *, - name: Optional[str]=None, - expect_handler: Optional[_ExpectHandler]=None, - chunk_size: int=256 * 1024, - show_index: bool=False, follow_symlinks: bool=False, - append_version: bool=False) -> AbstractResource: + def add_static(self, prefix, path, *, name=None, expect_handler=None, + chunk_size=256*1024, response_factory=StreamResponse, + show_index=False): """Add static files view. prefix - url prefix @@ -1048,88 +778,48 @@ class UrlDispatcher(AbstractRouter, Mapping[str, AbstractResource]): """ assert prefix.startswith('/') - if prefix.endswith('/'): - prefix = prefix[:-1] - resource = StaticResource(prefix, path, - name=name, - expect_handler=expect_handler, - chunk_size=chunk_size, - show_index=show_index, - follow_symlinks=follow_symlinks, - append_version=append_version) - self.register_resource(resource) - return resource - - def add_head(self, path: str, handler: _WebHandler, - **kwargs: Any) -> AbstractRoute: + if not prefix.endswith('/'): + prefix += '/' + route = StaticRoute(name, prefix, path, + expect_handler=expect_handler, + chunk_size=chunk_size, + response_factory=response_factory, + show_index=show_index) + self.register_route(route) + return route + + def add_head(self, *args, **kwargs): """ Shortcut for add_route with method HEAD """ - return self.add_route(hdrs.METH_HEAD, path, handler, **kwargs) + return self.add_route(hdrs.METH_HEAD, *args, **kwargs) - def add_options(self, path: str, handler: _WebHandler, - **kwargs: Any) -> AbstractRoute: + def add_get(self, *args, **kwargs): """ - Shortcut for add_route with method OPTIONS + Shortcut for add_route with method GET """ - return self.add_route(hdrs.METH_OPTIONS, path, handler, **kwargs) + return self.add_route(hdrs.METH_GET, *args, **kwargs) - def add_get(self, path: str, handler: _WebHandler, *, - name: Optional[str]=None, allow_head: bool=True, - **kwargs: Any) -> AbstractRoute: - """ - Shortcut for add_route with method GET, if allow_head is true another - route is added allowing head requests to the same endpoint - """ - resource = self.add_resource(path, name=name) - if allow_head: - resource.add_route(hdrs.METH_HEAD, handler, **kwargs) - return resource.add_route(hdrs.METH_GET, handler, **kwargs) - - def add_post(self, path: str, handler: _WebHandler, - **kwargs: Any) -> AbstractRoute: + def add_post(self, *args, **kwargs): """ Shortcut for add_route with method POST """ - return self.add_route(hdrs.METH_POST, path, handler, **kwargs) + return self.add_route(hdrs.METH_POST, *args, **kwargs) - def add_put(self, path: str, handler: _WebHandler, - **kwargs: Any) -> AbstractRoute: + def add_put(self, *args, **kwargs): """ Shortcut for add_route with method PUT """ - return self.add_route(hdrs.METH_PUT, path, handler, **kwargs) + return self.add_route(hdrs.METH_PUT, *args, **kwargs) - def add_patch(self, path: str, handler: _WebHandler, - **kwargs: Any) -> AbstractRoute: + def add_patch(self, *args, **kwargs): """ Shortcut for add_route with method PATCH """ - return self.add_route(hdrs.METH_PATCH, path, handler, **kwargs) + return self.add_route(hdrs.METH_PATCH, *args, **kwargs) - def add_delete(self, path: str, handler: _WebHandler, - **kwargs: Any) -> AbstractRoute: + def add_delete(self, *args, **kwargs): """ Shortcut for add_route with method DELETE """ - return self.add_route(hdrs.METH_DELETE, path, handler, **kwargs) - - def add_view(self, path: str, handler: Type[AbstractView], - **kwargs: Any) -> AbstractRoute: - """ - Shortcut for add_route with ANY methods for a class-based view - """ - return self.add_route(hdrs.METH_ANY, path, handler, **kwargs) - - def freeze(self) -> None: - super().freeze() - for resource in self._resources: - resource.freeze() - - def add_routes(self, routes: Iterable[AbstractRouteDef]) -> None: - """Append routes to route table. - - Parameter should be a sequence of RouteDef objects. - """ - for route_def in routes: - route_def.register(self) + return self.add_route(hdrs.METH_DELETE, *args, **kwargs) diff --git a/venv/Lib/site-packages/aiohttp/web_ws.py b/venv/Lib/site-packages/aiohttp/web_ws.py index 4c5e7ca5..8873225b 100644 --- a/venv/Lib/site-packages/aiohttp/web_ws.py +++ b/venv/Lib/site-packages/aiohttp/web_ws.py @@ -1,328 +1,192 @@ import asyncio -import base64 -import binascii -import hashlib import json -from typing import Any, Iterable, Optional, Tuple - -import async_timeout -import attr -from multidict import CIMultiDict - -from . import hdrs -from .abc import AbstractStreamWriter -from .helpers import call_later, set_result -from .http import ( - WS_CLOSED_MESSAGE, - WS_CLOSING_MESSAGE, - WS_KEY, - WebSocketError, - WebSocketReader, - WebSocketWriter, - WSMessage, -) -from .http import WSMsgType as WSMsgType -from .http import ws_ext_gen, ws_ext_parse -from .log import ws_logger -from .streams import EofStream, FlowControlDataQueue -from .typedefs import JSONDecoder, JSONEncoder -from .web_exceptions import HTTPBadRequest, HTTPException -from .web_request import BaseRequest -from .web_response import StreamResponse - -__all__ = ('WebSocketResponse', 'WebSocketReady', 'WSMsgType',) +import sys +import warnings +from collections import namedtuple + +from . import Timeout, hdrs +from ._ws_impl import (CLOSED_MESSAGE, WebSocketError, WSMessage, WSMsgType, + do_handshake) +from .errors import ClientDisconnectedError, HttpProcessingError +from .web_exceptions import (HTTPBadRequest, HTTPInternalServerError, + HTTPMethodNotAllowed) +from .web_reqrep import StreamResponse + +__all__ = ('WebSocketResponse', 'WebSocketReady', 'MsgType', 'WSMsgType',) + +PY_35 = sys.version_info >= (3, 5) +PY_352 = sys.version_info >= (3, 5, 2) THRESHOLD_CONNLOST_ACCESS = 5 -@attr.s(frozen=True, slots=True) -class WebSocketReady: - ok = attr.ib(type=bool) - protocol = attr.ib(type=Optional[str]) +# deprecated since 1.0 +MsgType = WSMsgType - def __bool__(self) -> bool: + +class WebSocketReady(namedtuple('WebSocketReady', 'ok protocol')): + def __bool__(self): return self.ok class WebSocketResponse(StreamResponse): - _length_check = False - def __init__(self, *, - timeout: float=10.0, receive_timeout: Optional[float]=None, - autoclose: bool=True, autoping: bool=True, - heartbeat: Optional[float]=None, - protocols: Iterable[str]=(), - compress: bool=True, max_msg_size: int=4*1024*1024) -> None: + timeout=10.0, autoclose=True, autoping=True, protocols=()): super().__init__(status=101) self._protocols = protocols - self._ws_protocol = None # type: Optional[str] - self._writer = None # type: Optional[WebSocketWriter] - self._reader = None # type: Optional[FlowControlDataQueue[WSMessage]] + self._protocol = None + self._writer = None + self._reader = None self._closed = False self._closing = False self._conn_lost = 0 - self._close_code = None # type: Optional[int] - self._loop = None # type: Optional[asyncio.AbstractEventLoop] - self._waiting = None # type: Optional[asyncio.Future[bool]] - self._exception = None # type: Optional[BaseException] + self._close_code = None + self._loop = None + self._waiting = False + self._exception = None self._timeout = timeout - self._receive_timeout = receive_timeout self._autoclose = autoclose self._autoping = autoping - self._heartbeat = heartbeat - self._heartbeat_cb = None - if heartbeat is not None: - self._pong_heartbeat = heartbeat / 2.0 - self._pong_response_cb = None - self._compress = compress - self._max_msg_size = max_msg_size - - def _cancel_heartbeat(self) -> None: - if self._pong_response_cb is not None: - self._pong_response_cb.cancel() - self._pong_response_cb = None - - if self._heartbeat_cb is not None: - self._heartbeat_cb.cancel() - self._heartbeat_cb = None - - def _reset_heartbeat(self) -> None: - self._cancel_heartbeat() - - if self._heartbeat is not None: - self._heartbeat_cb = call_later( - self._send_heartbeat, self._heartbeat, self._loop) - - def _send_heartbeat(self) -> None: - if self._heartbeat is not None and not self._closed: - # fire-and-forget a task is not perfect but maybe ok for - # sending ping. Otherwise we need a long-living heartbeat - # task in the class. - self._loop.create_task(self._writer.ping()) # type: ignore - - if self._pong_response_cb is not None: - self._pong_response_cb.cancel() - self._pong_response_cb = call_later( - self._pong_not_received, self._pong_heartbeat, self._loop) - - def _pong_not_received(self) -> None: - if self._req is not None and self._req.transport is not None: - self._closed = True - self._close_code = 1006 - self._exception = asyncio.TimeoutError() - self._req.transport.close() - async def prepare(self, request: BaseRequest) -> AbstractStreamWriter: + @asyncio.coroutine + def prepare(self, request): # make pre-check to don't hide it by do_handshake() exceptions - if self._payload_writer is not None: - return self._payload_writer - - protocol, writer = self._pre_start(request) - payload_writer = await super().prepare(request) - assert payload_writer is not None - self._post_start(request, protocol, writer) - await payload_writer.drain() - return payload_writer - - def _handshake(self, request: BaseRequest) -> Tuple['CIMultiDict[str]', - str, - bool, - bool]: - headers = request.headers - if 'websocket' != headers.get(hdrs.UPGRADE, '').lower().strip(): - raise HTTPBadRequest( - text=('No WebSocket UPGRADE hdr: {}\n Can ' - '"Upgrade" only to "WebSocket".') - .format(headers.get(hdrs.UPGRADE))) - - if 'upgrade' not in headers.get(hdrs.CONNECTION, '').lower(): - raise HTTPBadRequest( - text='No CONNECTION upgrade hdr: {}'.format( - headers.get(hdrs.CONNECTION))) - - # find common sub-protocol between client and server - protocol = None - if hdrs.SEC_WEBSOCKET_PROTOCOL in headers: - req_protocols = [str(proto.strip()) for proto in - headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(',')] - - for proto in req_protocols: - if proto in self._protocols: - protocol = proto - break - else: - # No overlap found: Return no protocol as per spec - ws_logger.warning( - 'Client protocols %r don’t overlap server-known ones %r', - req_protocols, self._protocols) - - # check supported version - version = headers.get(hdrs.SEC_WEBSOCKET_VERSION, '') - if version not in ('13', '8', '7'): - raise HTTPBadRequest( - text='Unsupported version: {}'.format(version)) - - # check client handshake for validity - key = headers.get(hdrs.SEC_WEBSOCKET_KEY) + resp_impl = self._start_pre_check(request) + if resp_impl is not None: + return resp_impl + + parser, protocol, writer = self._pre_start(request) + resp_impl = yield from super().prepare(request) + self._post_start(request, parser, protocol, writer) + return resp_impl + + def _pre_start(self, request): try: - if not key or len(base64.b64decode(key)) != 16: - raise HTTPBadRequest( - text='Handshake error: {!r}'.format(key)) - except binascii.Error: - raise HTTPBadRequest( - text='Handshake error: {!r}'.format(key)) from None - - accept_val = base64.b64encode( - hashlib.sha1(key.encode() + WS_KEY).digest()).decode() - response_headers = CIMultiDict( # type: ignore - {hdrs.UPGRADE: 'websocket', - hdrs.CONNECTION: 'upgrade', - hdrs.SEC_WEBSOCKET_ACCEPT: accept_val}) - - notakeover = False - compress = 0 - if self._compress: - extensions = headers.get(hdrs.SEC_WEBSOCKET_EXTENSIONS) - # Server side always get return with no exception. - # If something happened, just drop compress extension - compress, notakeover = ws_ext_parse(extensions, isserver=True) - if compress: - enabledext = ws_ext_gen(compress=compress, isserver=True, - server_notakeover=notakeover) - response_headers[hdrs.SEC_WEBSOCKET_EXTENSIONS] = enabledext - - if protocol: - response_headers[hdrs.SEC_WEBSOCKET_PROTOCOL] = protocol - return (response_headers, # type: ignore - protocol, - compress, - notakeover) - - def _pre_start(self, request: BaseRequest) -> Tuple[str, WebSocketWriter]: - self._loop = request._loop - - headers, protocol, compress, notakeover = self._handshake( - request) - - self._reset_heartbeat() - - self.set_status(101) - self.headers.update(headers) + status, headers, parser, writer, protocol = do_handshake( + request.method, request.headers, request.transport, + self._protocols) + except HttpProcessingError as err: + if err.code == 405: + raise HTTPMethodNotAllowed( + request.method, [hdrs.METH_GET], body=b'') + elif err.code == 400: + raise HTTPBadRequest(text=err.message, headers=err.headers) + else: # pragma: no cover + raise HTTPInternalServerError() from err + + if self.status != status: + self.set_status(status) + for k, v in headers: + self.headers[k] = v self.force_close() - self._compress = compress - transport = request._protocol.transport - assert transport is not None - writer = WebSocketWriter(request._protocol, - transport, - compress=compress, - notakeover=notakeover) - - return protocol, writer - - def _post_start(self, request: BaseRequest, - protocol: str, writer: WebSocketWriter) -> None: - self._ws_protocol = protocol + return parser, protocol, writer + + def _post_start(self, request, parser, protocol, writer): + self._reader = request._reader.set_parser(parser) self._writer = writer - loop = self._loop - assert loop is not None - self._reader = FlowControlDataQueue( - request._protocol, limit=2 ** 16, loop=loop) - request.protocol.set_parser(WebSocketReader( - self._reader, self._max_msg_size, compress=self._compress)) - # disable HTTP keepalive for WebSocket - request.protocol.keep_alive(False) - - def can_prepare(self, request: BaseRequest) -> WebSocketReady: + self._protocol = protocol + self._loop = request.app.loop + + def start(self, request): + warnings.warn('use .prepare(request) instead', DeprecationWarning) + # make pre-check to don't hide it by do_handshake() exceptions + resp_impl = self._start_pre_check(request) + if resp_impl is not None: + return resp_impl + + parser, protocol, writer = self._pre_start(request) + resp_impl = super().start(request) + self._post_start(request, parser, protocol, writer) + return resp_impl + + def can_prepare(self, request): if self._writer is not None: raise RuntimeError('Already started') try: - _, protocol, _, _ = self._handshake(request) - except HTTPException: + _, _, _, _, protocol = do_handshake( + request.method, request.headers, request.transport, + self._protocols) + except HttpProcessingError: return WebSocketReady(False, None) else: return WebSocketReady(True, protocol) + def can_start(self, request): + warnings.warn('use .can_prepare(request) instead', DeprecationWarning) + return self.can_prepare(request) + @property - def closed(self) -> bool: + def closed(self): return self._closed @property - def close_code(self) -> Optional[int]: + def close_code(self): return self._close_code @property - def ws_protocol(self) -> Optional[str]: - return self._ws_protocol - - @property - def compress(self) -> bool: - return self._compress + def protocol(self): + return self._protocol - def exception(self) -> Optional[BaseException]: + def exception(self): return self._exception - async def ping(self, message: bytes=b'') -> None: + def ping(self, message='b'): if self._writer is None: raise RuntimeError('Call .prepare() first') - await self._writer.ping(message) + if self._closed: + raise RuntimeError('websocket connection is closing') + self._writer.ping(message) - async def pong(self, message: bytes=b'') -> None: + def pong(self, message='b'): # unsolicited pong if self._writer is None: raise RuntimeError('Call .prepare() first') - await self._writer.pong(message) + if self._closed: + raise RuntimeError('websocket connection is closing') + self._writer.pong(message) - async def send_str(self, data: str, compress: Optional[bool]=None) -> None: + def send_str(self, data): if self._writer is None: raise RuntimeError('Call .prepare() first') + if self._closed: + raise RuntimeError('websocket connection is closing') if not isinstance(data, str): raise TypeError('data argument must be str (%r)' % type(data)) - await self._writer.send(data, binary=False, compress=compress) + self._writer.send(data, binary=False) - async def send_bytes(self, data: bytes, - compress: Optional[bool]=None) -> None: + def send_bytes(self, data): if self._writer is None: raise RuntimeError('Call .prepare() first') + if self._closed: + raise RuntimeError('websocket connection is closing') if not isinstance(data, (bytes, bytearray, memoryview)): raise TypeError('data argument must be byte-ish (%r)' % type(data)) - await self._writer.send(data, binary=True, compress=compress) + self._writer.send(data, binary=True) - async def send_json(self, data: Any, compress: Optional[bool]=None, *, - dumps: JSONEncoder=json.dumps) -> None: - await self.send_str(dumps(data), compress=compress) + def send_json(self, data, *, dumps=json.dumps): + self.send_str(dumps(data)) - async def write_eof(self) -> None: # type: ignore + @asyncio.coroutine + def write_eof(self): if self._eof_sent: return - if self._payload_writer is None: + if self._resp_impl is None: raise RuntimeError("Response has not been started") - await self.close() + yield from self.close() self._eof_sent = True - async def close(self, *, code: int=1000, message: bytes=b'') -> bool: + @asyncio.coroutine + def close(self, *, code=1000, message=b''): if self._writer is None: raise RuntimeError('Call .prepare() first') - self._cancel_heartbeat() - reader = self._reader - assert reader is not None - - # we need to break `receive()` cycle first, - # `close()` may be called from different task - if self._waiting is not None and not self._closed: - reader.feed_data(WS_CLOSING_MESSAGE, 0) - await self._waiting - if not self._closed: self._closed = True try: - await self._writer.close(code, message) - writer = self._payload_writer - assert writer is not None - await writer.drain() + self._writer.close(code, message) except (asyncio.CancelledError, asyncio.TimeoutError): self._close_code = 1006 raise @@ -334,22 +198,23 @@ class WebSocketResponse(StreamResponse): if self._closing: return True - reader = self._reader - assert reader is not None - try: - with async_timeout.timeout(self._timeout, loop=self._loop): - msg = await reader.read() - except asyncio.CancelledError: - self._close_code = 1006 - raise - except Exception as exc: - self._close_code = 1006 - self._exception = exc - return True - - if msg.type == WSMsgType.CLOSE: - self._close_code = msg.data - return True + begin = self._loop.time() + while self._loop.time() - begin < self._timeout: + try: + with Timeout(timeout=self._timeout, + loop=self._loop): + msg = yield from self._reader.read() + except asyncio.CancelledError: + self._close_code = 1006 + raise + except Exception as exc: + self._close_code = 1006 + self._exception = exc + return True + + if msg.type == WSMsgType.CLOSE: + self._close_code = msg.data + return True self._close_code = 1006 self._exception = asyncio.TimeoutError() @@ -357,100 +222,99 @@ class WebSocketResponse(StreamResponse): else: return False - async def receive(self, timeout: Optional[float]=None) -> WSMessage: + @asyncio.coroutine + def receive(self): if self._reader is None: raise RuntimeError('Call .prepare() first') + if self._waiting: + raise RuntimeError('Concurrent call to receive() is not allowed') - loop = self._loop - assert loop is not None - while True: - if self._waiting is not None: - raise RuntimeError( - 'Concurrent call to receive() is not allowed') - - if self._closed: - self._conn_lost += 1 - if self._conn_lost >= THRESHOLD_CONNLOST_ACCESS: - raise RuntimeError('WebSocket connection is closed.') - return WS_CLOSED_MESSAGE - elif self._closing: - return WS_CLOSING_MESSAGE + self._waiting = True + try: + while True: + if self._closed: + self._conn_lost += 1 + if self._conn_lost >= THRESHOLD_CONNLOST_ACCESS: + raise RuntimeError('WebSocket connection is closed.') + return CLOSED_MESSAGE - try: - self._waiting = loop.create_future() try: - with async_timeout.timeout( - timeout or self._receive_timeout, loop=self._loop): - msg = await self._reader.read() - self._reset_heartbeat() - finally: - waiter = self._waiting - set_result(waiter, True) - self._waiting = None - except (asyncio.CancelledError, asyncio.TimeoutError): - self._close_code = 1006 - raise - except EofStream: - self._close_code = 1000 - await self.close() - return WSMessage(WSMsgType.CLOSED, None, None) - except WebSocketError as exc: - self._close_code = exc.code - await self.close(code=exc.code) - return WSMessage(WSMsgType.ERROR, exc, None) - except Exception as exc: - self._exception = exc - self._closing = True - self._close_code = 1006 - await self.close() - return WSMessage(WSMsgType.ERROR, exc, None) - - if msg.type == WSMsgType.CLOSE: - self._closing = True - self._close_code = msg.data - if not self._closed and self._autoclose: - await self.close() - elif msg.type == WSMsgType.CLOSING: - self._closing = True - elif msg.type == WSMsgType.PING and self._autoping: - await self.pong(msg.data) - continue - elif msg.type == WSMsgType.PONG and self._autoping: - continue - - return msg - - async def receive_str(self, *, timeout: Optional[float]=None) -> str: - msg = await self.receive(timeout) + msg = yield from self._reader.read() + except (asyncio.CancelledError, asyncio.TimeoutError): + raise + except WebSocketError as exc: + self._close_code = exc.code + yield from self.close(code=exc.code) + return WSMessage(WSMsgType.ERROR, exc, None) + except ClientDisconnectedError: + self._closed = True + self._close_code = 1006 + return WSMessage(WSMsgType.CLOSE, None, None) + except Exception as exc: + self._exception = exc + self._closing = True + self._close_code = 1006 + yield from self.close() + return WSMessage(WSMsgType.ERROR, exc, None) + + if msg.type == WSMsgType.CLOSE: + self._closing = True + self._close_code = msg.data + if not self._closed and self._autoclose: + yield from self.close() + return msg + if msg.type == WSMsgType.PING and self._autoping: + self.pong(msg.data) + elif msg.type == WSMsgType.PONG and self._autoping: + continue + else: + return msg + finally: + self._waiting = False + + @asyncio.coroutine + def receive_msg(self): + warnings.warn( + 'receive_msg() coroutine is deprecated. use receive() instead', + DeprecationWarning) + return (yield from self.receive()) + + @asyncio.coroutine + def receive_str(self): + msg = yield from self.receive() if msg.type != WSMsgType.TEXT: raise TypeError( - "Received message {}:{!r} is not WSMsgType.TEXT".format( - msg.type, msg.data)) + "Received message {}:{!r} is not str".format(msg.type, + msg.data)) return msg.data - async def receive_bytes(self, *, timeout: Optional[float]=None) -> bytes: - msg = await self.receive(timeout) + @asyncio.coroutine + def receive_bytes(self): + msg = yield from self.receive() if msg.type != WSMsgType.BINARY: raise TypeError( "Received message {}:{!r} is not bytes".format(msg.type, msg.data)) return msg.data - async def receive_json(self, *, loads: JSONDecoder=json.loads, - timeout: Optional[float]=None) -> Any: - data = await self.receive_str(timeout=timeout) + @asyncio.coroutine + def receive_json(self, *, loads=json.loads): + data = yield from self.receive_str() return loads(data) - async def write(self, data: bytes) -> None: + def write(self, data): raise RuntimeError("Cannot call .write() for websocket") - def __aiter__(self) -> 'WebSocketResponse': - return self + if PY_35: + def __aiter__(self): + return self + + if not PY_352: # pragma: no cover + __aiter__ = asyncio.coroutine(__aiter__) - async def __anext__(self) -> WSMessage: - msg = await self.receive() - if msg.type in (WSMsgType.CLOSE, - WSMsgType.CLOSING, - WSMsgType.CLOSED): - raise StopAsyncIteration # NOQA - return msg + @asyncio.coroutine + def __anext__(self): + msg = yield from self.receive() + if msg.type == WSMsgType.CLOSE: + raise StopAsyncIteration # NOQA + return msg diff --git a/venv/Lib/site-packages/aiohttp/worker.py b/venv/Lib/site-packages/aiohttp/worker.py index 73ba6e38..9d079ccb 100644 --- a/venv/Lib/site-packages/aiohttp/worker.py +++ b/venv/Lib/site-packages/aiohttp/worker.py @@ -4,30 +4,15 @@ import asyncio import os import re import signal +import ssl import sys -from types import FrameType -from typing import Any, Awaitable, Callable, Optional, Union # noqa +import gunicorn.workers.base as base from gunicorn.config import AccessLogFormat as GunicornAccessLogFormat -from gunicorn.workers import base -from aiohttp import web +from aiohttp.helpers import AccessLogger, ensure_future -from .helpers import set_result -from .web_app import Application -from .web_log import AccessLogger - -try: - import ssl - SSLContext = ssl.SSLContext # noqa -except ImportError: # pragma: no cover - ssl = None # type: ignore - SSLContext = object # type: ignore - - -__all__ = ('GunicornWebWorker', - 'GunicornUVLoopWebWorker', - 'GunicornTokioWebWorker') +__all__ = ('GunicornWebWorker', 'GunicornUVLoopWebWorker') class GunicornWebWorker(base.Worker): @@ -35,14 +20,13 @@ class GunicornWebWorker(base.Worker): DEFAULT_AIOHTTP_LOG_FORMAT = AccessLogger.LOG_FORMAT DEFAULT_GUNICORN_LOG_FORMAT = GunicornAccessLogFormat.default - def __init__(self, *args: Any, **kw: Any) -> None: # pragma: no cover + def __init__(self, *args, **kw): # pragma: no cover super().__init__(*args, **kw) - self._task = None # type: Optional[asyncio.Task[None]] + self.servers = {} self.exit_code = 0 - self._notify_waiter = None # type: Optional[asyncio.Future[bool]] - def init_process(self) -> None: + def init_process(self): # create new event_loop after fork asyncio.get_event_loop().close() @@ -51,56 +35,71 @@ class GunicornWebWorker(base.Worker): super().init_process() - def run(self) -> None: - self._task = self.loop.create_task(self._run()) + def run(self): + self.loop.run_until_complete(self.wsgi.startup()) + self._runner = ensure_future(self._run(), loop=self.loop) - try: # ignore all finalization problems - self.loop.run_until_complete(self._task) - except Exception: - self.log.exception("Exception in gunicorn worker") - if sys.version_info >= (3, 6): - self.loop.run_until_complete(self.loop.shutdown_asyncgens()) - self.loop.close() + try: + self.loop.run_until_complete(self._runner) + finally: + self.loop.close() sys.exit(self.exit_code) - async def _run(self) -> None: - if isinstance(self.wsgi, Application): - app = self.wsgi - elif asyncio.iscoroutinefunction(self.wsgi): - app = await self.wsgi() - else: - raise RuntimeError("wsgi app should be either Application or " - "async function returning Application, got {}" - .format(self.wsgi)) - access_log = self.log.access_log if self.cfg.accesslog else None - runner = web.AppRunner(app, - logger=self.log, - keepalive_timeout=self.cfg.keepalive, - access_log=access_log, - access_log_format=self._get_valid_log_format( - self.cfg.access_log_format)) - await runner.setup() + def make_handler(self, app): + return app.make_handler( + logger=self.log, + slow_request_timeout=self.cfg.timeout, + keepalive_timeout=self.cfg.keepalive, + access_log=self.log.access_log, + access_log_format=self._get_valid_log_format( + self.cfg.access_log_format)) + + @asyncio.coroutine + def close(self): + if self.servers: + servers = self.servers + self.servers = None + + # stop accepting connections + for server, handler in servers.items(): + self.log.info("Stopping server: %s, connections: %s", + self.pid, len(handler.connections)) + server.close() + yield from server.wait_closed() + + # send on_shutdown event + yield from self.wsgi.shutdown() + + # stop alive connections + tasks = [ + handler.finish_connections( + timeout=self.cfg.graceful_timeout / 100 * 95) + for handler in servers.values()] + yield from asyncio.gather(*tasks, loop=self.loop) + + # cleanup application + yield from self.wsgi.cleanup() + + @asyncio.coroutine + def _run(self): ctx = self._create_ssl_context(self.cfg) if self.cfg.is_ssl else None - runner = runner - assert runner is not None - server = runner.server - assert server is not None for sock in self.sockets: - site = web.SockSite( - runner, sock, ssl_context=ctx, - shutdown_timeout=self.cfg.graceful_timeout / 100 * 95) - await site.start() + handler = self.make_handler(self.wsgi) + srv = yield from self.loop.create_server(handler, sock=sock.sock, + ssl=ctx) + self.servers[srv] = handler # If our parent changed then we shut down. pid = os.getpid() try: - while self.alive: # type: ignore + while self.alive: self.notify() - cnt = server.requests_count + cnt = sum(handler.requests_count + for handler in self.servers.values()) if self.cfg.max_requests and cnt > self.cfg.max_requests: self.alive = False self.log.info("Max requests, shutting down: %s", self) @@ -109,32 +108,14 @@ class GunicornWebWorker(base.Worker): self.alive = False self.log.info("Parent changed, shutting down: %s", self) else: - await self._wait_next_notify() + yield from asyncio.sleep(1.0, loop=self.loop) + except BaseException: pass - await runner.cleanup() - - def _wait_next_notify(self) -> 'asyncio.Future[bool]': - self._notify_waiter_done() + yield from self.close() - loop = self.loop - assert loop is not None - self._notify_waiter = waiter = loop.create_future() - self.loop.call_later(1.0, self._notify_waiter_done, waiter) - - return waiter - - def _notify_waiter_done(self, waiter: 'asyncio.Future[bool]'=None) -> None: - if waiter is None: - waiter = self._notify_waiter - if waiter is not None: - set_result(waiter, True) - - if waiter is self._notify_waiter: - self._notify_waiter = None - - def init_signals(self) -> None: + def init_signals(self): # Set up signals through the event loop API. self.loop.add_signal_handler(signal.SIGQUIT, self.handle_quit, @@ -160,30 +141,19 @@ class GunicornWebWorker(base.Worker): signal.siginterrupt(signal.SIGTERM, False) signal.siginterrupt(signal.SIGUSR1, False) - def handle_quit(self, sig: int, frame: FrameType) -> None: + def handle_quit(self, sig, frame): self.alive = False - # worker_int callback - self.cfg.worker_int(self) - - # wakeup closing process - self._notify_waiter_done() - - def handle_abort(self, sig: int, frame: FrameType) -> None: + def handle_abort(self, sig, frame): self.alive = False self.exit_code = 1 - self.cfg.worker_abort(self) - sys.exit(1) @staticmethod - def _create_ssl_context(cfg: Any) -> 'SSLContext': + def _create_ssl_context(cfg): """ Creates SSLContext instance for usage in asyncio.create_server. See ssl.SSLSocket.__init__ for more details. """ - if ssl is None: # pragma: no cover - raise RuntimeError('SSL is not supported.') - ctx = ssl.SSLContext(cfg.ssl_version) ctx.load_cert_chain(cfg.certfile, cfg.keyfile) ctx.verify_mode = cfg.cert_reqs @@ -193,7 +163,7 @@ class GunicornWebWorker(base.Worker): ctx.set_ciphers(cfg.ciphers) return ctx - def _get_valid_log_format(self, source_format: str) -> str: + def _get_valid_log_format(self, source_format): if source_format == self.DEFAULT_GUNICORN_LOG_FORMAT: return self.DEFAULT_AIOHTTP_LOG_FORMAT elif re.search(r'%\([^\)]+\)', source_format): @@ -201,7 +171,7 @@ class GunicornWebWorker(base.Worker): "Gunicorn's style options in form of `%(name)s` are not " "supported for the log formatting. Please use aiohttp's " "format specification to configure access log formatting: " - "http://docs.aiohttp.org/en/stable/logging.html" + "http://aiohttp.readthedocs.io/en/stable/logging.html" "#format-specification" ) else: @@ -210,7 +180,7 @@ class GunicornWebWorker(base.Worker): class GunicornUVLoopWebWorker(GunicornWebWorker): - def init_process(self) -> None: + def init_process(self): import uvloop # Close any existing event loop before setting a @@ -223,20 +193,3 @@ class GunicornUVLoopWebWorker(GunicornWebWorker): asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) super().init_process() - - -class GunicornTokioWebWorker(GunicornWebWorker): - - def init_process(self) -> None: # pragma: no cover - import tokio - - # Close any existing event loop before setting a - # new policy. - asyncio.get_event_loop().close() - - # Setup tokio policy, so that every - # asyncio.get_event_loop() will create an instance - # of tokio event loop. - asyncio.set_event_loop_policy(tokio.EventLoopPolicy()) - - super().init_process() diff --git a/venv/Lib/site-packages/aiohttp/wsgi.py b/venv/Lib/site-packages/aiohttp/wsgi.py new file mode 100644 index 00000000..251c044a --- /dev/null +++ b/venv/Lib/site-packages/aiohttp/wsgi.py @@ -0,0 +1,235 @@ +"""wsgi server. + +TODO: + * proxy protocol + * x-forward security + * wsgi file support (os.sendfile) +""" + +import asyncio +import inspect +import io +import os +import socket +import sys +from urllib.parse import urlsplit + +import aiohttp +from aiohttp import hdrs, server + +__all__ = ('WSGIServerHttpProtocol',) + + +class WSGIServerHttpProtocol(server.ServerHttpProtocol): + """HTTP Server that implements the Python WSGI protocol. + + It uses 'wsgi.async' of 'True'. 'wsgi.input' can behave differently + depends on 'readpayload' constructor parameter. If readpayload is set to + True, wsgi server reads all incoming data into BytesIO object and + sends it as 'wsgi.input' environ var. If readpayload is set to false + 'wsgi.input' is a StreamReader and application should read incoming + data with "yield from environ['wsgi.input'].read()". It defaults to False. + """ + + SCRIPT_NAME = os.environ.get('SCRIPT_NAME', '') + + def __init__(self, app, readpayload=False, is_ssl=False, *args, **kw): + super().__init__(*args, **kw) + + self.wsgi = app + self.is_ssl = is_ssl + self.readpayload = readpayload + + def create_wsgi_response(self, message): + return WsgiResponse(self.writer, message) + + def create_wsgi_environ(self, message, payload): + uri_parts = urlsplit(message.path) + + environ = { + 'wsgi.input': payload, + 'wsgi.errors': sys.stderr, + 'wsgi.version': (1, 0), + 'wsgi.async': True, + 'wsgi.multithread': False, + 'wsgi.multiprocess': False, + 'wsgi.run_once': False, + 'wsgi.file_wrapper': FileWrapper, + 'SERVER_SOFTWARE': aiohttp.HttpMessage.SERVER_SOFTWARE, + 'REQUEST_METHOD': message.method, + 'QUERY_STRING': uri_parts.query or '', + 'RAW_URI': message.path, + 'SERVER_PROTOCOL': 'HTTP/%s.%s' % message.version + } + + script_name = self.SCRIPT_NAME + + for hdr_name, hdr_value in message.headers.items(): + hdr_name = hdr_name.upper() + if hdr_name == 'SCRIPT_NAME': + script_name = hdr_value + elif hdr_name == 'CONTENT-TYPE': + environ['CONTENT_TYPE'] = hdr_value + continue + elif hdr_name == 'CONTENT-LENGTH': + environ['CONTENT_LENGTH'] = hdr_value + continue + + key = 'HTTP_%s' % hdr_name.replace('-', '_') + if key in environ: + hdr_value = '%s,%s' % (environ[key], hdr_value) + + environ[key] = hdr_value + + url_scheme = environ.get('HTTP_X_FORWARDED_PROTO') + if url_scheme is None: + url_scheme = 'https' if self.is_ssl else 'http' + environ['wsgi.url_scheme'] = url_scheme + + # authors should be aware that REMOTE_HOST and REMOTE_ADDR + # may not qualify the remote addr + # also SERVER_PORT variable MUST be set to the TCP/IP port number on + # which this request is received from the client. + # http://www.ietf.org/rfc/rfc3875 + + family = self.transport.get_extra_info('socket').family + if family in (socket.AF_INET, socket.AF_INET6): + peername = self.transport.get_extra_info('peername') + environ['REMOTE_ADDR'] = peername[0] + environ['REMOTE_PORT'] = str(peername[1]) + http_host = message.headers.get("HOST", None) + if http_host: + hostport = http_host.split(":") + environ['SERVER_NAME'] = hostport[0] + if len(hostport) > 1: + environ['SERVER_PORT'] = str(hostport[1]) + else: + environ['SERVER_PORT'] = '80' + else: + # SERVER_NAME should be set to value of Host header, but this + # header is not required. In this case we shoud set it to local + # address of socket + sockname = self.transport.get_extra_info('sockname') + environ['SERVER_NAME'] = sockname[0] + environ['SERVER_PORT'] = str(sockname[1]) + else: + # We are behind reverse proxy, so get all vars from headers + for header in ('REMOTE_ADDR', 'REMOTE_PORT', + 'SERVER_NAME', 'SERVER_PORT'): + environ[header] = message.headers.get(header, '') + + path_info = uri_parts.path + if script_name: + path_info = path_info.split(script_name, 1)[-1] + + environ['PATH_INFO'] = path_info + environ['SCRIPT_NAME'] = script_name + + environ['async.reader'] = self.reader + environ['async.writer'] = self.writer + + return environ + + @asyncio.coroutine + def handle_request(self, message, payload): + """Handle a single HTTP request""" + now = self._loop.time() + + if self.readpayload: + wsgiinput = io.BytesIO() + wsgiinput.write((yield from payload.read())) + wsgiinput.seek(0) + payload = wsgiinput + + environ = self.create_wsgi_environ(message, payload) + response = self.create_wsgi_response(message) + + riter = self.wsgi(environ, response.start_response) + if isinstance(riter, asyncio.Future) or inspect.isgenerator(riter): + riter = yield from riter + + resp = response.response + try: + for item in riter: + if isinstance(item, asyncio.Future): + item = yield from item + yield from resp.write(item) + + yield from resp.write_eof() + finally: + if hasattr(riter, 'close'): + riter.close() + + if resp.keep_alive(): + self.keep_alive(True) + + self.log_access( + message, environ, response.response, self._loop.time() - now) + + +class FileWrapper: + """Custom file wrapper.""" + + def __init__(self, fobj, chunk_size=8192): + self.fobj = fobj + self.chunk_size = chunk_size + if hasattr(fobj, 'close'): + self.close = fobj.close + + def __iter__(self): + return self + + def __next__(self): + data = self.fobj.read(self.chunk_size) + if data: + return data + raise StopIteration + + +class WsgiResponse: + """Implementation of start_response() callable as specified by PEP 3333""" + + status = None + + HOP_HEADERS = { + hdrs.CONNECTION, + hdrs.KEEP_ALIVE, + hdrs.PROXY_AUTHENTICATE, + hdrs.PROXY_AUTHORIZATION, + hdrs.TE, + hdrs.TRAILER, + hdrs.TRANSFER_ENCODING, + hdrs.UPGRADE, + } + + def __init__(self, writer, message): + self.writer = writer + self.message = message + + def start_response(self, status, headers, exc_info=None): + if exc_info: + try: + if self.status: + raise exc_info[1] + finally: + exc_info = None + + status_code = int(status.split(' ', 1)[0]) + + self.status = status + resp = self.response = aiohttp.Response( + self.writer, status_code, + self.message.version, self.message.should_close) + resp.HOP_HEADERS = self.HOP_HEADERS + for name, value in headers: + resp.add_header(name, value) + + if resp.has_chunked_hdr: + resp.enable_chunked_encoding() + + # send headers immediately for websocket connection + if status_code == 101 and resp.upgrade and resp.websocket: + resp.send_headers() + else: + resp._send_headers = True + return self.response.write diff --git a/venv/Lib/site-packages/discord/ext/commands/bot.py b/venv/Lib/site-packages/discord/ext/commands/bot.py index 0833b20a..9280136d 100644 --- a/venv/Lib/site-packages/discord/ext/commands/bot.py +++ b/venv/Lib/site-packages/discord/ext/commands/bot.py @@ -999,7 +999,6 @@ class Bot(BotBase, discord.Client): """ pass - class AutoShardedBot(BotBase, discord.AutoShardedClient): """This is similar to :class:`.Bot` except that it is inherited from :class:`discord.AutoShardedClient` instead. diff --git a/venv/Lib/site-packages/websockets-3.4.dist-info/DESCRIPTION.rst b/venv/Lib/site-packages/websockets-3.4.dist-info/DESCRIPTION.rst new file mode 100644 index 00000000..fd3773ce --- /dev/null +++ b/venv/Lib/site-packages/websockets-3.4.dist-info/DESCRIPTION.rst @@ -0,0 +1,30 @@ +WebSockets +========== + +``websockets`` is a library for developing WebSocket servers_ and clients_ in +Python. It implements `RFC 6455`_ with a focus on correctness and simplicity. +It passes the `Autobahn Testsuite`_. + +Built on top of Python's asynchronous I/O support introduced in `PEP 3156`_, +it provides an API based on coroutines, making it easy to write highly +concurrent applications. + +Installation is as simple as ``pip install websockets``. It requires Python ≥ +3.4 or Python 3.3 with the ``asyncio`` module, which is available with ``pip +install asyncio``. + +Documentation is available on `Read the Docs`_. + +Bug reports, patches and suggestions welcome! Just open an issue_ or send a +`pull request`_. + +.. _servers: https://github.com/aaugustin/websockets/blob/master/example/server.py +.. _clients: https://github.com/aaugustin/websockets/blob/master/example/client.py +.. _RFC 6455: http://tools.ietf.org/html/rfc6455 +.. _Autobahn Testsuite: https://github.com/aaugustin/websockets/blob/master/compliance/README.rst +.. _PEP 3156: http://www.python.org/dev/peps/pep-3156/ +.. _Read the Docs: https://websockets.readthedocs.io/ +.. _issue: https://github.com/aaugustin/websockets/issues/new +.. _pull request: https://github.com/aaugustin/websockets/compare/ + + diff --git a/venv/Lib/site-packages/aiohttp-3.6.2.dist-info/INSTALLER b/venv/Lib/site-packages/websockets-3.4.dist-info/INSTALLER similarity index 100% rename from venv/Lib/site-packages/aiohttp-3.6.2.dist-info/INSTALLER rename to venv/Lib/site-packages/websockets-3.4.dist-info/INSTALLER diff --git a/venv/Lib/site-packages/websockets-3.4.dist-info/METADATA b/venv/Lib/site-packages/websockets-3.4.dist-info/METADATA new file mode 100644 index 00000000..a97ff01a --- /dev/null +++ b/venv/Lib/site-packages/websockets-3.4.dist-info/METADATA @@ -0,0 +1,52 @@ +Metadata-Version: 2.0 +Name: websockets +Version: 3.4 +Summary: An implementation of the WebSocket Protocol (RFC 6455) +Home-page: https://github.com/aaugustin/websockets +Author: Aymeric Augustin +Author-email: aymeric.augustin@m4x.org +License: BSD +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Requires-Dist: asyncio; python_version=="3.3" + +WebSockets +========== + +``websockets`` is a library for developing WebSocket servers_ and clients_ in +Python. It implements `RFC 6455`_ with a focus on correctness and simplicity. +It passes the `Autobahn Testsuite`_. + +Built on top of Python's asynchronous I/O support introduced in `PEP 3156`_, +it provides an API based on coroutines, making it easy to write highly +concurrent applications. + +Installation is as simple as ``pip install websockets``. It requires Python ≥ +3.4 or Python 3.3 with the ``asyncio`` module, which is available with ``pip +install asyncio``. + +Documentation is available on `Read the Docs`_. + +Bug reports, patches and suggestions welcome! Just open an issue_ or send a +`pull request`_. + +.. _servers: https://github.com/aaugustin/websockets/blob/master/example/server.py +.. _clients: https://github.com/aaugustin/websockets/blob/master/example/client.py +.. _RFC 6455: http://tools.ietf.org/html/rfc6455 +.. _Autobahn Testsuite: https://github.com/aaugustin/websockets/blob/master/compliance/README.rst +.. _PEP 3156: http://www.python.org/dev/peps/pep-3156/ +.. _Read the Docs: https://websockets.readthedocs.io/ +.. _issue: https://github.com/aaugustin/websockets/issues/new +.. _pull request: https://github.com/aaugustin/websockets/compare/ + + diff --git a/venv/Lib/site-packages/websockets-3.4.dist-info/RECORD b/venv/Lib/site-packages/websockets-3.4.dist-info/RECORD new file mode 100644 index 00000000..a87673de --- /dev/null +++ b/venv/Lib/site-packages/websockets-3.4.dist-info/RECORD @@ -0,0 +1,56 @@ +websockets-3.4.dist-info/DESCRIPTION.rst,sha256=Xfv_W4k7cI7wsQ7_GkxVUWox9Fj9Kbicr9vGzVaN-Rk,1264 +websockets-3.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +websockets-3.4.dist-info/METADATA,sha256=GrwKnapJ4AN94EN2RS1qyayejMXWV3K2wuQHzdueBAQ,2105 +websockets-3.4.dist-info/RECORD,, +websockets-3.4.dist-info/WHEEL,sha256=4fkP9V5fUlnPlEu2h0nt7u0cPpJipYsJO32nXNevnFk,106 +websockets-3.4.dist-info/metadata.json,sha256=6s9m0aXolRcZ2UodIViSHcTIqQuL6gJPJir-ZZl4stA,1000 +websockets-3.4.dist-info/top_level.txt,sha256=EcCngZER7Li9SDhzH7kpxRCzPMkWrtR98pBqycxQDZc,27 +websockets/__init__.py,sha256=dtzzVSk5GjukX2OhwZhjfYhQBWTQCzYYoruzoivf8f4,383 +websockets/__pycache__/__init__.cpython-36.pyc,, +websockets/__pycache__/client.cpython-36.pyc,, +websockets/__pycache__/compatibility.cpython-36.pyc,, +websockets/__pycache__/exceptions.cpython-36.pyc,, +websockets/__pycache__/framing.cpython-36.pyc,, +websockets/__pycache__/handshake.cpython-36.pyc,, +websockets/__pycache__/http.cpython-36.pyc,, +websockets/__pycache__/protocol.cpython-36.pyc,, +websockets/__pycache__/server.cpython-36.pyc,, +websockets/__pycache__/test_client_server.cpython-36.pyc,, +websockets/__pycache__/test_framing.cpython-36.pyc,, +websockets/__pycache__/test_handshake.cpython-36.pyc,, +websockets/__pycache__/test_http.cpython-36.pyc,, +websockets/__pycache__/test_protocol.cpython-36.pyc,, +websockets/__pycache__/test_speedups.cpython-36.pyc,, +websockets/__pycache__/test_uri.cpython-36.pyc,, +websockets/__pycache__/test_utils.cpython-36.pyc,, +websockets/__pycache__/uri.cpython-36.pyc,, +websockets/__pycache__/utils.cpython-36.pyc,, +websockets/__pycache__/version.cpython-36.pyc,, +websockets/client.py,sha256=wr9k4IjcLoN8xLSCIJF06A4j43Ji-u0xvQdd6lDGuAY,8330 +websockets/compatibility.py,sha256=DfAlt7rra9enxR0TO0qrAnFLumTGmqhMyhANw3cv9IA,1567 +websockets/exceptions.py,sha256=zOGatgy9IM75Ofzsh2qKI2NTfnR9yD5ap3sy4KN_tKk,2309 +websockets/framing.py,sha256=lBcIIC82qgNgtcsBSBI4d8C2ydjw_ErI_DgvhieSSUM,6083 +websockets/handshake.py,sha256=tqZJV9kTRjm1LOX5ZjFVOFEjE1zs1W2YaIgKu6vjDJ4,4310 +websockets/http.py,sha256=G7LHgfMqjs5dYaLwxxzpa2rR14wWcz_qu4qW8SLsA9Q,6421 +websockets/protocol.py,sha256=jUku43eyUR8qYl6NCpGprK3SRGtoc982jP4jv1HQIm0,26694 +websockets/py35/__init__.py,sha256=yYRQ_76YWF-La7UK4uZwOcPEIp4CE3RwXZ99BUM7qX4,152 +websockets/py35/__pycache__/__init__.cpython-36.pyc,, +websockets/py35/__pycache__/client.cpython-36.pyc,, +websockets/py35/__pycache__/client_server.cpython-36.pyc,, +websockets/py35/__pycache__/server.cpython-36.pyc,, +websockets/py35/client.py,sha256=nveWJBe17u584UR6NjYl-bU52zmsZe-p2HMIcw9ooCk,568 +websockets/py35/client_server.py,sha256=Y0SWqtC4qhy02lr3Tn-HftM1pan9vMKHEgMu-kOcY5A,1341 +websockets/py35/server.py,sha256=vmxXu77VNvOPUC3opeMJRcUG6Vs8bEzLhRSGUiYclYQ,589 +websockets/server.py,sha256=jpT0HGvZag17QP373wTGpR6-ZcHmZGuaLo2ih_yB7v0,20691 +websockets/speedups.cp36-win_amd64.pyd,sha256=FwNTiJryIYA5m_Nmkmu1koT-BM8jFFayeK1MO-_f9_k,11264 +websockets/test_client_server.py,sha256=3g87ybCp6rkXWt2Dvi00_xKOlT5dOy_Q9O6PyGAmGDc,23413 +websockets/test_framing.py,sha256=zWqDNwDAF6qHwV9j9rFiEePxu7s5bVFqHaDZFLi3MOY,5371 +websockets/test_handshake.py,sha256=TKyzYrqRURklO3dEH1oq8fFn64repe2U415ARLJ5DoE,4223 +websockets/test_http.py,sha256=DnmICytpKL1iswq_TA9SR1VO3Md3T5asUEP9i__-8OM,4663 +websockets/test_protocol.py,sha256=xh-AMIMJrgRrquzHS5mry9ZGoa_yQcXXUnx2inhnwM0,30556 +websockets/test_speedups.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +websockets/test_uri.py,sha256=JDs1Orabj9WWrykp6nUKhyPIe7w-uRmAoGgQKPntDBs,932 +websockets/test_utils.py,sha256=eNGhH9RsTOxcEhUbJRs04du_r3EIGmXYPuTSOwE5uDY,1441 +websockets/uri.py,sha256=80xWOSHYFcnFjGJ5tyxkUVFkha2wp2FFepSxbXYts9w,1517 +websockets/utils.py,sha256=Qt5rpZiL_6u4KgS5WFSXTrFhmDbZzydA6LGBM6DacMY,277 +websockets/version.py,sha256=mCvUBEXtlj9qxGDKLmrm21r_qKAXR2K2pfPYy6W7sCg,16 diff --git a/venv/Lib/site-packages/websockets-8.1.dist-info/WHEEL b/venv/Lib/site-packages/websockets-3.4.dist-info/WHEEL similarity index 68% rename from venv/Lib/site-packages/websockets-8.1.dist-info/WHEEL rename to venv/Lib/site-packages/websockets-3.4.dist-info/WHEEL index 3740b8bc..1a39a6a4 100644 --- a/venv/Lib/site-packages/websockets-8.1.dist-info/WHEEL +++ b/venv/Lib/site-packages/websockets-3.4.dist-info/WHEEL @@ -1,5 +1,5 @@ Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.6) +Generator: bdist_wheel (0.29.0) Root-Is-Purelib: false Tag: cp36-cp36m-win_amd64 diff --git a/venv/Lib/site-packages/websockets-3.4.dist-info/metadata.json b/venv/Lib/site-packages/websockets-3.4.dist-info/metadata.json new file mode 100644 index 00000000..62e3286d --- /dev/null +++ b/venv/Lib/site-packages/websockets-3.4.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6"], "extensions": {"python.details": {"contacts": [{"email": "aymeric.augustin@m4x.org", "name": "Aymeric Augustin", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/aaugustin/websockets"}}}, "extras": [], "generator": "bdist_wheel (0.29.0)", "license": "BSD", "metadata_version": "2.0", "name": "websockets", "run_requires": [{"environment": "python_version==\"3.3\"", "requires": ["asyncio"]}], "summary": "An implementation of the WebSocket Protocol (RFC 6455)", "version": "3.4"} \ No newline at end of file diff --git a/venv/Lib/site-packages/websockets-3.4.dist-info/top_level.txt b/venv/Lib/site-packages/websockets-3.4.dist-info/top_level.txt new file mode 100644 index 00000000..51d75266 --- /dev/null +++ b/venv/Lib/site-packages/websockets-3.4.dist-info/top_level.txt @@ -0,0 +1,2 @@ +websockets +websockets/py35 diff --git a/venv/Lib/site-packages/websockets-8.1.dist-info/INSTALLER b/venv/Lib/site-packages/websockets-8.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e3..00000000 --- a/venv/Lib/site-packages/websockets-8.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/Lib/site-packages/websockets-8.1.dist-info/LICENSE b/venv/Lib/site-packages/websockets-8.1.dist-info/LICENSE deleted file mode 100644 index b2962adb..00000000 --- a/venv/Lib/site-packages/websockets-8.1.dist-info/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2013-2019 Aymeric Augustin and contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of websockets nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/Lib/site-packages/websockets-8.1.dist-info/METADATA b/venv/Lib/site-packages/websockets-8.1.dist-info/METADATA deleted file mode 100644 index 7dd36828..00000000 --- a/venv/Lib/site-packages/websockets-8.1.dist-info/METADATA +++ /dev/null @@ -1,167 +0,0 @@ -Metadata-Version: 2.1 -Name: websockets -Version: 8.1 -Summary: An implementation of the WebSocket Protocol (RFC 6455 & 7692) -Home-page: https://github.com/aaugustin/websockets -Author: Aymeric Augustin -Author-email: aymeric.augustin@m4x.org -License: BSD -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Requires-Python: >=3.6.1 - -.. image:: logo/horizontal.svg - :width: 480px - :alt: websockets - -|rtd| |pypi-v| |pypi-pyversions| |pypi-l| |pypi-wheel| |circleci| |codecov| - -.. |rtd| image:: https://readthedocs.org/projects/websockets/badge/?version=latest - :target: https://websockets.readthedocs.io/ - -.. |pypi-v| image:: https://img.shields.io/pypi/v/websockets.svg - :target: https://pypi.python.org/pypi/websockets - -.. |pypi-pyversions| image:: https://img.shields.io/pypi/pyversions/websockets.svg - :target: https://pypi.python.org/pypi/websockets - -.. |pypi-l| image:: https://img.shields.io/pypi/l/websockets.svg - :target: https://pypi.python.org/pypi/websockets - -.. |pypi-wheel| image:: https://img.shields.io/pypi/wheel/websockets.svg - :target: https://pypi.python.org/pypi/websockets - -.. |circleci| image:: https://img.shields.io/circleci/project/github/aaugustin/websockets.svg - :target: https://circleci.com/gh/aaugustin/websockets - -.. |codecov| image:: https://codecov.io/gh/aaugustin/websockets/branch/master/graph/badge.svg - :target: https://codecov.io/gh/aaugustin/websockets - -What is ``websockets``? ------------------------ - -``websockets`` is a library for building WebSocket servers_ and clients_ in -Python with a focus on correctness and simplicity. - -.. _servers: https://github.com/aaugustin/websockets/blob/master/example/server.py -.. _clients: https://github.com/aaugustin/websockets/blob/master/example/client.py - -Built on top of ``asyncio``, Python's standard asynchronous I/O framework, it -provides an elegant coroutine-based API. - -`Documentation is available on Read the Docs. `_ - -Here's how a client sends and receives messages: - -.. copy-pasted because GitHub doesn't support the include directive - -.. code:: python - - #!/usr/bin/env python - - import asyncio - import websockets - - async def hello(uri): - async with websockets.connect(uri) as websocket: - await websocket.send("Hello world!") - await websocket.recv() - - asyncio.get_event_loop().run_until_complete( - hello('ws://localhost:8765')) - -And here's an echo server: - -.. code:: python - - #!/usr/bin/env python - - import asyncio - import websockets - - async def echo(websocket, path): - async for message in websocket: - await websocket.send(message) - - asyncio.get_event_loop().run_until_complete( - websockets.serve(echo, 'localhost', 8765)) - asyncio.get_event_loop().run_forever() - -Does that look good? - -`Get started with the tutorial! `_ - -Why should I use ``websockets``? --------------------------------- - -The development of ``websockets`` is shaped by four principles: - -1. **Simplicity**: all you need to understand is ``msg = await ws.recv()`` and - ``await ws.send(msg)``; ``websockets`` takes care of managing connections - so you can focus on your application. - -2. **Robustness**: ``websockets`` is built for production; for example it was - the only library to `handle backpressure correctly`_ before the issue - became widely known in the Python community. - -3. **Quality**: ``websockets`` is heavily tested. Continuous integration fails - under 100% branch coverage. Also it passes the industry-standard `Autobahn - Testsuite`_. - -4. **Performance**: memory use is configurable. An extension written in C - accelerates expensive operations. It's pre-compiled for Linux, macOS and - Windows and packaged in the wheel format for each system and Python version. - -Documentation is a first class concern in the project. Head over to `Read the -Docs`_ and see for yourself. - -.. _Read the Docs: https://websockets.readthedocs.io/ -.. _handle backpressure correctly: https://vorpus.org/blog/some-thoughts-on-asynchronous-api-design-in-a-post-asyncawait-world/#websocket-servers -.. _Autobahn Testsuite: https://github.com/aaugustin/websockets/blob/master/compliance/README.rst - -Why shouldn't I use ``websockets``? ------------------------------------ - -* If you prefer callbacks over coroutines: ``websockets`` was created to - provide the best coroutine-based API to manage WebSocket connections in - Python. Pick another library for a callback-based API. -* If you're looking for a mixed HTTP / WebSocket library: ``websockets`` aims - at being an excellent implementation of :rfc:`6455`: The WebSocket Protocol - and :rfc:`7692`: Compression Extensions for WebSocket. Its support for HTTP - is minimal — just enough for a HTTP health check. -* If you want to use Python 2: ``websockets`` builds upon ``asyncio`` which - only works on Python 3. ``websockets`` requires Python ≥ 3.6.1. - -What else? ----------- - -Bug reports, patches and suggestions are welcome! - -To report a security vulnerability, please use the `Tidelift security -contact`_. Tidelift will coordinate the fix and disclosure. - -.. _Tidelift security contact: https://tidelift.com/security - -For anything else, please open an issue_ or send a `pull request`_. - -.. _issue: https://github.com/aaugustin/websockets/issues/new -.. _pull request: https://github.com/aaugustin/websockets/compare/ - -Participants must uphold the `Contributor Covenant code of conduct`_. - -.. _Contributor Covenant code of conduct: https://github.com/aaugustin/websockets/blob/master/CODE_OF_CONDUCT.md - -``websockets`` is released under the `BSD license`_. - -.. _BSD license: https://github.com/aaugustin/websockets/blob/master/LICENSE - - diff --git a/venv/Lib/site-packages/websockets-8.1.dist-info/RECORD b/venv/Lib/site-packages/websockets-8.1.dist-info/RECORD deleted file mode 100644 index b9538900..00000000 --- a/venv/Lib/site-packages/websockets-8.1.dist-info/RECORD +++ /dev/null @@ -1,44 +0,0 @@ -websockets-8.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -websockets-8.1.dist-info/LICENSE,sha256=ioiWDA1qqLOPqm7mFFl9vxjg6iK6IIhO890x00sqbQk,1536 -websockets-8.1.dist-info/METADATA,sha256=Ybp0HGQ7VBJZMyP-ZNors83guDrgCvSa8mdIypZsX3U,6200 -websockets-8.1.dist-info/RECORD,, -websockets-8.1.dist-info/WHEEL,sha256=uQaeujkjkt7SlmOZGXO6onhwBPrzw2WTI2otbCZzdNI,106 -websockets-8.1.dist-info/top_level.txt,sha256=KtfDkU36u2JojZLmzHTIQUQ39q6RdOuHhI-rvY5J-FM,33 -websockets/__init__.py,sha256=358xBAefIahVJA8sDJbA-zKGd-tVUqKoUJdIDjc8cjQ,1314 -websockets/__main__.py,sha256=U3euVZyLJmWYySdr4gP0TmvqiPbfGgKHf1N25E2y8z4,6420 -websockets/__pycache__/__init__.cpython-36.pyc,, -websockets/__pycache__/__main__.cpython-36.pyc,, -websockets/__pycache__/auth.cpython-36.pyc,, -websockets/__pycache__/client.cpython-36.pyc,, -websockets/__pycache__/exceptions.cpython-36.pyc,, -websockets/__pycache__/framing.cpython-36.pyc,, -websockets/__pycache__/handshake.cpython-36.pyc,, -websockets/__pycache__/headers.cpython-36.pyc,, -websockets/__pycache__/http.cpython-36.pyc,, -websockets/__pycache__/protocol.cpython-36.pyc,, -websockets/__pycache__/server.cpython-36.pyc,, -websockets/__pycache__/typing.cpython-36.pyc,, -websockets/__pycache__/uri.cpython-36.pyc,, -websockets/__pycache__/utils.cpython-36.pyc,, -websockets/__pycache__/version.cpython-36.pyc,, -websockets/auth.py,sha256=R11zxLlNsK-RHlsdryL3pXgv5fWwJACJnqBpwHESGF8,5414 -websockets/client.py,sha256=3xRLPV7pDusiPHKV6eF4YUFazKyGX7jFwhMk-Vy4Tw8,21215 -websockets/exceptions.py,sha256=CLfGkck8Qt-_ICMfj0E8NaGgEotgp_6XGoDaxn_zthY,8824 -websockets/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -websockets/extensions/__pycache__/__init__.cpython-36.pyc,, -websockets/extensions/__pycache__/base.cpython-36.pyc,, -websockets/extensions/__pycache__/permessage_deflate.cpython-36.pyc,, -websockets/extensions/base.py,sha256=pefUdApzb7Z0zV_AGlMVlpE3Bj3QcTFplBfApaoptgs,2784 -websockets/extensions/permessage_deflate.py,sha256=FT_kqFSHBp0PnI988kS99U1CeNaYI41DQMxOjo53Mxk,21730 -websockets/framing.py,sha256=DgeRjpeom5ehX2gb838DUy1g2dhPBVMWncmZQyojhnA,10244 -websockets/handshake.py,sha256=GoSlNCymiSZdkm4QWzMjPx-20QF1-w7KhfQ7ODxPEw8,6152 -websockets/headers.py,sha256=guRd8T_ppb7OEPXCDH8D4p3hsZcksNPF3YUNp9afXQM,15069 -websockets/http.py,sha256=-ay6psjIla3YU-a_0UW3GcXXTBeDqiyanhEg-l_nW88,11826 -websockets/protocol.py,sha256=I8p-T-aDsz5m9OZ181I0r8R0jiz1EBcF2EhWFHHYTEw,55030 -websockets/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -websockets/server.py,sha256=WZ86dfWq3uLDF2f8o0wG1glsJyYGaMKwwdzLA9CZL3s,38186 -websockets/speedups.cp36-win_amd64.pyd,sha256=-xmeYRCiN2buHVC9KafFBWTmHkRz6rurGhSibHUlrXk,12288 -websockets/typing.py,sha256=R-OvOXKtMXeu49At4J5hAg9s3Da3iT77cM9luddy33k,1305 -websockets/uri.py,sha256=q1VLxJE3q9xEWJI1FfVEqeHtSE1-YOob2sAmvSVXHyU,2244 -websockets/utils.py,sha256=wFZSnRYfkz94nN1L9vITaZShs56_I5cOEXeE6Iez7oY,376 -websockets/version.py,sha256=6nmfcHh_ydnzhw9ujCQU5lRV4fyb84UgtEV7Ud6QGL8,16 diff --git a/venv/Lib/site-packages/websockets-8.1.dist-info/top_level.txt b/venv/Lib/site-packages/websockets-8.1.dist-info/top_level.txt deleted file mode 100644 index 8f846ff9..00000000 --- a/venv/Lib/site-packages/websockets-8.1.dist-info/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -websockets -websockets/extensions diff --git a/venv/Lib/site-packages/websockets/__init__.py b/venv/Lib/site-packages/websockets/__init__.py index ea1d829a..b394c569 100644 --- a/venv/Lib/site-packages/websockets/__init__.py +++ b/venv/Lib/site-packages/websockets/__init__.py @@ -1,55 +1,17 @@ # This relies on each of the submodules having an __all__ variable. -from .auth import * # noqa -from .client import * # noqa -from .exceptions import * # noqa -from .protocol import * # noqa -from .server import * # noqa -from .typing import * # noqa -from .uri import * # noqa -from .version import version as __version__ # noqa +from .client import * +from .exceptions import * +from .protocol import * +from .server import * +from .uri import * +from .version import version as __version__ # noqa -__all__ = [ - "AbortHandshake", - "basic_auth_protocol_factory", - "BasicAuthWebSocketServerProtocol", - "connect", - "ConnectionClosed", - "ConnectionClosedError", - "ConnectionClosedOK", - "Data", - "DuplicateParameter", - "ExtensionHeader", - "ExtensionParameter", - "InvalidHandshake", - "InvalidHeader", - "InvalidHeaderFormat", - "InvalidHeaderValue", - "InvalidMessage", - "InvalidOrigin", - "InvalidParameterName", - "InvalidParameterValue", - "InvalidState", - "InvalidStatusCode", - "InvalidUpgrade", - "InvalidURI", - "NegotiationError", - "Origin", - "parse_uri", - "PayloadTooBig", - "ProtocolError", - "RedirectHandshake", - "SecurityError", - "serve", - "Subprotocol", - "unix_connect", - "unix_serve", - "WebSocketClientProtocol", - "WebSocketCommonProtocol", - "WebSocketException", - "WebSocketProtocolError", - "WebSocketServer", - "WebSocketServerProtocol", - "WebSocketURI", -] +__all__ = ( + client.__all__ + + exceptions.__all__ + + protocol.__all__ + + server.__all__ + + uri.__all__ +) diff --git a/venv/Lib/site-packages/websockets/auth.py b/venv/Lib/site-packages/websockets/auth.py deleted file mode 100644 index ae204b8d..00000000 --- a/venv/Lib/site-packages/websockets/auth.py +++ /dev/null @@ -1,160 +0,0 @@ -""" -:mod:`websockets.auth` provides HTTP Basic Authentication according to -:rfc:`7235` and :rfc:`7617`. - -""" - - -import functools -import http -from typing import Any, Awaitable, Callable, Iterable, Optional, Tuple, Type, Union - -from .exceptions import InvalidHeader -from .headers import build_www_authenticate_basic, parse_authorization_basic -from .http import Headers -from .server import HTTPResponse, WebSocketServerProtocol - - -__all__ = ["BasicAuthWebSocketServerProtocol", "basic_auth_protocol_factory"] - -Credentials = Tuple[str, str] - - -def is_credentials(value: Any) -> bool: - try: - username, password = value - except (TypeError, ValueError): - return False - else: - return isinstance(username, str) and isinstance(password, str) - - -class BasicAuthWebSocketServerProtocol(WebSocketServerProtocol): - """ - WebSocket server protocol that enforces HTTP Basic Auth. - - """ - - def __init__( - self, - *args: Any, - realm: str, - check_credentials: Callable[[str, str], Awaitable[bool]], - **kwargs: Any, - ) -> None: - self.realm = realm - self.check_credentials = check_credentials - super().__init__(*args, **kwargs) - - async def process_request( - self, path: str, request_headers: Headers - ) -> Optional[HTTPResponse]: - """ - Check HTTP Basic Auth and return a HTTP 401 or 403 response if needed. - - If authentication succeeds, the username of the authenticated user is - stored in the ``username`` attribute. - - """ - try: - authorization = request_headers["Authorization"] - except KeyError: - return ( - http.HTTPStatus.UNAUTHORIZED, - [("WWW-Authenticate", build_www_authenticate_basic(self.realm))], - b"Missing credentials\n", - ) - - try: - username, password = parse_authorization_basic(authorization) - except InvalidHeader: - return ( - http.HTTPStatus.UNAUTHORIZED, - [("WWW-Authenticate", build_www_authenticate_basic(self.realm))], - b"Unsupported credentials\n", - ) - - if not await self.check_credentials(username, password): - return ( - http.HTTPStatus.UNAUTHORIZED, - [("WWW-Authenticate", build_www_authenticate_basic(self.realm))], - b"Invalid credentials\n", - ) - - self.username = username - - return await super().process_request(path, request_headers) - - -def basic_auth_protocol_factory( - realm: str, - credentials: Optional[Union[Credentials, Iterable[Credentials]]] = None, - check_credentials: Optional[Callable[[str, str], Awaitable[bool]]] = None, - create_protocol: Type[ - BasicAuthWebSocketServerProtocol - ] = BasicAuthWebSocketServerProtocol, -) -> Callable[[Any], BasicAuthWebSocketServerProtocol]: - """ - Protocol factory that enforces HTTP Basic Auth. - - ``basic_auth_protocol_factory`` is designed to integrate with - :func:`~websockets.server.serve` like this:: - - websockets.serve( - ..., - create_protocol=websockets.basic_auth_protocol_factory( - realm="my dev server", - credentials=("hello", "iloveyou"), - ) - ) - - ``realm`` indicates the scope of protection. It should contain only ASCII - characters because the encoding of non-ASCII characters is undefined. - Refer to section 2.2 of :rfc:`7235` for details. - - ``credentials`` defines hard coded authorized credentials. It can be a - ``(username, password)`` pair or a list of such pairs. - - ``check_credentials`` defines a coroutine that checks whether credentials - are authorized. This coroutine receives ``username`` and ``password`` - arguments and returns a :class:`bool`. - - One of ``credentials`` or ``check_credentials`` must be provided but not - both. - - By default, ``basic_auth_protocol_factory`` creates a factory for building - :class:`BasicAuthWebSocketServerProtocol` instances. You can override this - with the ``create_protocol`` parameter. - - :param realm: scope of protection - :param credentials: hard coded credentials - :param check_credentials: coroutine that verifies credentials - :raises TypeError: if the credentials argument has the wrong type - - """ - if (credentials is None) == (check_credentials is None): - raise TypeError("provide either credentials or check_credentials") - - if credentials is not None: - if is_credentials(credentials): - - async def check_credentials(username: str, password: str) -> bool: - return (username, password) == credentials - - elif isinstance(credentials, Iterable): - credentials_list = list(credentials) - if all(is_credentials(item) for item in credentials_list): - credentials_dict = dict(credentials_list) - - async def check_credentials(username: str, password: str) -> bool: - return credentials_dict.get(username) == password - - else: - raise TypeError(f"invalid credentials argument: {credentials}") - - else: - raise TypeError(f"invalid credentials argument: {credentials}") - - return functools.partial( - create_protocol, realm=realm, check_credentials=check_credentials - ) diff --git a/venv/Lib/site-packages/websockets/client.py b/venv/Lib/site-packages/websockets/client.py index eb58f9f4..544223e4 100644 --- a/venv/Lib/site-packages/websockets/client.py +++ b/venv/Lib/site-packages/websockets/client.py @@ -1,584 +1,231 @@ """ -:mod:`websockets.client` defines the WebSocket client APIs. +The :mod:`websockets.client` module defines a simple WebSocket client API. """ import asyncio import collections.abc -import functools -import logging -import warnings -from types import TracebackType -from typing import Any, Generator, List, Optional, Sequence, Tuple, Type, cast - -from .exceptions import ( - InvalidHandshake, - InvalidHeader, - InvalidMessage, - InvalidStatusCode, - NegotiationError, - RedirectHandshake, - SecurityError, -) -from .extensions.base import ClientExtensionFactory, Extension -from .extensions.permessage_deflate import ClientPerMessageDeflateFactory -from .handshake import build_request, check_response -from .headers import ( - build_authorization_basic, - build_extension, - build_subprotocol, - parse_extension, - parse_subprotocol, -) -from .http import USER_AGENT, Headers, HeadersLike, read_response -from .protocol import WebSocketCommonProtocol -from .typing import ExtensionHeader, Origin, Subprotocol -from .uri import WebSocketURI, parse_uri +from .exceptions import InvalidHandshake, InvalidMessage, InvalidStatusCode +from .handshake import build_request, check_response +from .http import USER_AGENT, build_headers, read_response +from .protocol import CONNECTING, OPEN, WebSocketCommonProtocol +from .uri import parse_uri -__all__ = ["connect", "unix_connect", "WebSocketClientProtocol"] -logger = logging.getLogger(__name__) +__all__ = ['connect', 'WebSocketClientProtocol'] class WebSocketClientProtocol(WebSocketCommonProtocol): """ - :class:`~asyncio.Protocol` subclass implementing a WebSocket client. + Complete WebSocket client implementation as an :class:`asyncio.Protocol`. This class inherits most of its methods from :class:`~websockets.protocol.WebSocketCommonProtocol`. """ - is_client = True - side = "client" - - def __init__( - self, - *, - origin: Optional[Origin] = None, - extensions: Optional[Sequence[ClientExtensionFactory]] = None, - subprotocols: Optional[Sequence[Subprotocol]] = None, - extra_headers: Optional[HeadersLike] = None, - **kwargs: Any, - ) -> None: - self.origin = origin - self.available_extensions = extensions - self.available_subprotocols = subprotocols - self.extra_headers = extra_headers - super().__init__(**kwargs) - - def write_http_request(self, path: str, headers: Headers) -> None: + state = CONNECTING + + @asyncio.coroutine + def write_http_request(self, path, headers): """ Write request line and headers to the HTTP request. """ self.path = path - self.request_headers = headers - - logger.debug("%s > GET %s HTTP/1.1", self.side, path) - logger.debug("%s > %r", self.side, headers) + self.request_headers = build_headers(headers) + self.raw_request_headers = headers # Since the path and headers only contain ASCII characters, # we can keep this simple. - request = f"GET {path} HTTP/1.1\r\n" - request += str(headers) + request = ['GET {path} HTTP/1.1'.format(path=path)] + request.extend('{}: {}'.format(k, v) for k, v in headers) + request.append('\r\n') + request = '\r\n'.join(request).encode() - self.transport.write(request.encode()) + self.writer.write(request) - async def read_http_response(self) -> Tuple[int, Headers]: + @asyncio.coroutine + def read_http_response(self): """ Read status line and headers from the HTTP response. - If the response contains a body, it may be read from ``self.reader`` - after this coroutine returns. + Raise :exc:`~websockets.exceptions.InvalidMessage` if the HTTP message + is malformed or isn't an HTTP/1.1 GET request. - :raises ~websockets.exceptions.InvalidMessage: if the HTTP message is - malformed or isn't an HTTP/1.1 GET response + Don't attempt to read the response body because WebSocket handshake + responses don't have one. If the response contains a body, it may be + read from ``self.reader`` after this coroutine returns. """ try: - status_code, reason, headers = await read_response(self.reader) - except Exception as exc: - raise InvalidMessage("did not receive a valid HTTP response") from exc + status_code, headers = yield from read_response(self.reader) + except ValueError as exc: + raise InvalidMessage("Malformed HTTP message") from exc - logger.debug("%s < HTTP/1.1 %d %s", self.side, status_code, reason) - logger.debug("%s < %r", self.side, headers) - - self.response_headers = headers + self.response_headers = build_headers(headers) + self.raw_response_headers = headers return status_code, self.response_headers - @staticmethod - def process_extensions( - headers: Headers, - available_extensions: Optional[Sequence[ClientExtensionFactory]], - ) -> List[Extension]: + def process_subprotocol(self, get_header, subprotocols=None): """ - Handle the Sec-WebSocket-Extensions HTTP response header. - - Check that each extension is supported, as well as its parameters. - - Return the list of accepted extensions. - - Raise :exc:`~websockets.exceptions.InvalidHandshake` to abort the - connection. - - :rfc:`6455` leaves the rules up to the specification of each - :extension. - - To provide this level of flexibility, for each extension accepted by - the server, we check for a match with each extension available in the - client configuration. If no match is found, an exception is raised. - - If several variants of the same extension are accepted by the server, - it may be configured severel times, which won't make sense in general. - Extensions must implement their own requirements. For this purpose, - the list of previously accepted extensions is provided. - - Other requirements, for example related to mandatory extensions or the - order of extensions, may be implemented by overriding this method. + Handle the Sec-WebSocket-Protocol HTTP header. """ - accepted_extensions: List[Extension] = [] - - header_values = headers.get_all("Sec-WebSocket-Extensions") - - if header_values: - - if available_extensions is None: - raise InvalidHandshake("no extensions supported") - - parsed_header_values: List[ExtensionHeader] = sum( - [parse_extension(header_value) for header_value in header_values], [] - ) - - for name, response_params in parsed_header_values: - - for extension_factory in available_extensions: - - # Skip non-matching extensions based on their name. - if extension_factory.name != name: - continue - - # Skip non-matching extensions based on their params. - try: - extension = extension_factory.process_response_params( - response_params, accepted_extensions - ) - except NegotiationError: - continue - - # Add matching extension to the final list. - accepted_extensions.append(extension) - - # Break out of the loop once we have a match. - break - - # If we didn't break from the loop, no extension in our list - # matched what the server sent. Fail the connection. - else: - raise NegotiationError( - f"Unsupported extension: " - f"name = {name}, params = {response_params}" - ) - - return accepted_extensions - - @staticmethod - def process_subprotocol( - headers: Headers, available_subprotocols: Optional[Sequence[Subprotocol]] - ) -> Optional[Subprotocol]: + subprotocol = get_header('Sec-WebSocket-Protocol') + if subprotocol: + if subprotocols is None or subprotocol not in subprotocols: + raise InvalidHandshake( + "Unknown subprotocol: {}".format(subprotocol)) + return subprotocol + + @asyncio.coroutine + def handshake(self, wsuri, + origin=None, subprotocols=None, extra_headers=None): """ - Handle the Sec-WebSocket-Protocol HTTP response header. - - Check that it contains exactly one supported subprotocol. - - Return the selected subprotocol. - - """ - subprotocol: Optional[Subprotocol] = None - - header_values = headers.get_all("Sec-WebSocket-Protocol") - - if header_values: - - if available_subprotocols is None: - raise InvalidHandshake("no subprotocols supported") - - parsed_header_values: Sequence[Subprotocol] = sum( - [parse_subprotocol(header_value) for header_value in header_values], [] - ) - - if len(parsed_header_values) > 1: - subprotocols = ", ".join(parsed_header_values) - raise InvalidHandshake(f"multiple subprotocols: {subprotocols}") - - subprotocol = parsed_header_values[0] - - if subprotocol not in available_subprotocols: - raise NegotiationError(f"unsupported subprotocol: {subprotocol}") + Perform the client side of the opening handshake. - return subprotocol + If provided, ``origin`` sets the Origin HTTP header. - async def handshake( - self, - wsuri: WebSocketURI, - origin: Optional[Origin] = None, - available_extensions: Optional[Sequence[ClientExtensionFactory]] = None, - available_subprotocols: Optional[Sequence[Subprotocol]] = None, - extra_headers: Optional[HeadersLike] = None, - ) -> None: - """ - Perform the client side of the opening handshake. + If provided, ``subprotocols`` is a list of supported subprotocols in + order of decreasing preference. - :param origin: sets the Origin HTTP header - :param available_extensions: list of supported extensions in the order - in which they should be used - :param available_subprotocols: list of supported subprotocols in order - of decreasing preference - :param extra_headers: sets additional HTTP request headers; it must be - a :class:`~websockets.http.Headers` instance, a - :class:`~collections.abc.Mapping`, or an iterable of ``(name, - value)`` pairs - :raises ~websockets.exceptions.InvalidHandshake: if the handshake - fails + If provided, ``extra_headers`` sets additional HTTP request headers. + It must be a mapping or an iterable of (name, value) pairs. """ - request_headers = Headers() + headers = [] + set_header = lambda k, v: headers.append((k, v)) - if wsuri.port == (443 if wsuri.secure else 80): # pragma: no cover - request_headers["Host"] = wsuri.host + if wsuri.port == (443 if wsuri.secure else 80): # pragma: no cover + set_header('Host', wsuri.host) else: - request_headers["Host"] = f"{wsuri.host}:{wsuri.port}" - - if wsuri.user_info: - request_headers["Authorization"] = build_authorization_basic( - *wsuri.user_info - ) - + set_header('Host', '{}:{}'.format(wsuri.host, wsuri.port)) if origin is not None: - request_headers["Origin"] = origin - - key = build_request(request_headers) - - if available_extensions is not None: - extensions_header = build_extension( - [ - (extension_factory.name, extension_factory.get_request_params()) - for extension_factory in available_extensions - ] - ) - request_headers["Sec-WebSocket-Extensions"] = extensions_header - - if available_subprotocols is not None: - protocol_header = build_subprotocol(available_subprotocols) - request_headers["Sec-WebSocket-Protocol"] = protocol_header - + set_header('Origin', origin) + if subprotocols is not None: + set_header('Sec-WebSocket-Protocol', ', '.join(subprotocols)) if extra_headers is not None: - if isinstance(extra_headers, Headers): - extra_headers = extra_headers.raw_items() - elif isinstance(extra_headers, collections.abc.Mapping): + if isinstance(extra_headers, collections.abc.Mapping): extra_headers = extra_headers.items() for name, value in extra_headers: - request_headers[name] = value + set_header(name, value) + set_header('User-Agent', USER_AGENT) - request_headers.setdefault("User-Agent", USER_AGENT) + key = build_request(set_header) - self.write_http_request(wsuri.resource_name, request_headers) + yield from self.write_http_request(wsuri.resource_name, headers) - status_code, response_headers = await self.read_http_response() - if status_code in (301, 302, 303, 307, 308): - if "Location" not in response_headers: - raise InvalidHeader("Location") - raise RedirectHandshake(response_headers["Location"]) - elif status_code != 101: - raise InvalidStatusCode(status_code) + status_code, headers = yield from self.read_http_response() + get_header = lambda k: headers.get(k, '') - check_response(response_headers, key) + if status_code != 101: + raise InvalidStatusCode(status_code) - self.extensions = self.process_extensions( - response_headers, available_extensions - ) + check_response(get_header, key) - self.subprotocol = self.process_subprotocol( - response_headers, available_subprotocols - ) + self.subprotocol = self.process_subprotocol(get_header, subprotocols) - self.connection_open() + assert self.state == CONNECTING + self.state = OPEN + self.opening_handshake.set_result(True) -class Connect: +@asyncio.coroutine +def connect(uri, *, + create_protocol=None, + timeout=10, max_size=2 ** 20, max_queue=2 ** 5, + read_limit=2 ** 16, write_limit=2 ** 16, + loop=None, legacy_recv=False, klass=None, + origin=None, subprotocols=None, extra_headers=None, + **kwds): """ - Connect to the WebSocket server at the given ``uri``. - - Awaiting :func:`connect` yields a :class:`WebSocketClientProtocol` which - can then be used to send and receive messages. + This coroutine connects to a WebSocket server at a given ``uri``. - :func:`connect` can also be used as a asynchronous context manager. In - that case, the connection is closed when exiting the context. + It yields a :class:`WebSocketClientProtocol` which can then be used to + send and receive messages. :func:`connect` is a wrapper around the event loop's - :meth:`~asyncio.loop.create_connection` method. Unknown keyword arguments - are passed to :meth:`~asyncio.loop.create_connection`. + :meth:`~asyncio.BaseEventLoop.create_connection` method. Unknown keyword + arguments are passed to :meth:`~asyncio.BaseEventLoop.create_connection`. For example, you can set the ``ssl`` keyword argument to a :class:`~ssl.SSLContext` to enforce some TLS settings. When connecting to - a ``wss://`` URI, if this argument isn't provided explicitly, - :func:`ssl.create_default_context` is called to create a context. - - You can connect to a different host and port from those found in ``uri`` - by setting ``host`` and ``port`` keyword arguments. This only changes the - destination of the TCP connection. The host name from ``uri`` is still - used in the TLS handshake for secure connections and in the ``Host`` HTTP - header. - - The ``create_protocol`` parameter allows customizing the - :class:`~asyncio.Protocol` that manages the connection. It should be a - callable or class accepting the same arguments as - :class:`WebSocketClientProtocol` and returning an instance of - :class:`WebSocketClientProtocol` or a subclass. It defaults to - :class:`WebSocketClientProtocol`. + a ``wss://`` URI, if this argument isn't provided explicitly, it's set to + ``True``, which means Python's default :class:`~ssl.SSLContext` is used. + + The behavior of the ``timeout``, ``max_size``, and ``max_queue``, + ``read_limit``, and ``write_limit`` optional arguments is described in the + documentation of :class:`~websockets.protocol.WebSocketCommonProtocol`. - The behavior of ``ping_interval``, ``ping_timeout``, ``close_timeout``, - ``max_size``, ``max_queue``, ``read_limit``, and ``write_limit`` is - described in :class:`~websockets.protocol.WebSocketCommonProtocol`. + The ``create_protocol`` parameter allows customizing the asyncio protocol + that manages the connection. It should be a callable or class accepting + the same arguments as :class:`WebSocketClientProtocol` and returning a + :class:`WebSocketClientProtocol` instance. It defaults to + :class:`WebSocketClientProtocol`. :func:`connect` also accepts the following optional arguments: - * ``compression`` is a shortcut to configure compression extensions; - by default it enables the "permessage-deflate" extension; set it to - ``None`` to disable compression * ``origin`` sets the Origin HTTP header - * ``extensions`` is a list of supported extensions in order of - decreasing preference * ``subprotocols`` is a list of supported subprotocols in order of decreasing preference - * ``extra_headers`` sets additional HTTP request headers; it can be a - :class:`~websockets.http.Headers` instance, a - :class:`~collections.abc.Mapping`, or an iterable of ``(name, value)`` - pairs - - :raises ~websockets.uri.InvalidURI: if ``uri`` is invalid - :raises ~websockets.handshake.InvalidHandshake: if the opening handshake - fails - - """ - - MAX_REDIRECTS_ALLOWED = 10 - - def __init__( - self, - uri: str, - *, - path: Optional[str] = None, - create_protocol: Optional[Type[WebSocketClientProtocol]] = None, - ping_interval: float = 20, - ping_timeout: float = 20, - close_timeout: Optional[float] = None, - max_size: int = 2 ** 20, - max_queue: int = 2 ** 5, - read_limit: int = 2 ** 16, - write_limit: int = 2 ** 16, - loop: Optional[asyncio.AbstractEventLoop] = None, - legacy_recv: bool = False, - klass: Optional[Type[WebSocketClientProtocol]] = None, - timeout: Optional[float] = None, - compression: Optional[str] = "deflate", - origin: Optional[Origin] = None, - extensions: Optional[Sequence[ClientExtensionFactory]] = None, - subprotocols: Optional[Sequence[Subprotocol]] = None, - extra_headers: Optional[HeadersLike] = None, - **kwargs: Any, - ) -> None: - # Backwards compatibility: close_timeout used to be called timeout. - if timeout is None: - timeout = 10 - else: - warnings.warn("rename timeout to close_timeout", DeprecationWarning) - # If both are specified, timeout is ignored. - if close_timeout is None: - close_timeout = timeout - - # Backwards compatibility: create_protocol used to be called klass. - if klass is None: - klass = WebSocketClientProtocol - else: - warnings.warn("rename klass to create_protocol", DeprecationWarning) - # If both are specified, klass is ignored. - if create_protocol is None: - create_protocol = klass - - if loop is None: - loop = asyncio.get_event_loop() - - wsuri = parse_uri(uri) - if wsuri.secure: - kwargs.setdefault("ssl", True) - elif kwargs.get("ssl") is not None: - raise ValueError( - "connect() received a ssl argument for a ws:// URI, " - "use a wss:// URI to enable TLS" - ) - - if compression == "deflate": - if extensions is None: - extensions = [] - if not any( - extension_factory.name == ClientPerMessageDeflateFactory.name - for extension_factory in extensions - ): - extensions = list(extensions) + [ - ClientPerMessageDeflateFactory(client_max_window_bits=True) - ] - elif compression is not None: - raise ValueError(f"unsupported compression: {compression}") - - factory = functools.partial( - create_protocol, - ping_interval=ping_interval, - ping_timeout=ping_timeout, - close_timeout=close_timeout, - max_size=max_size, - max_queue=max_queue, - read_limit=read_limit, - write_limit=write_limit, - loop=loop, - host=wsuri.host, - port=wsuri.port, - secure=wsuri.secure, - legacy_recv=legacy_recv, - origin=origin, - extensions=extensions, - subprotocols=subprotocols, - extra_headers=extra_headers, - ) - - if path is None: - host: Optional[str] - port: Optional[int] - if kwargs.get("sock") is None: - host, port = wsuri.host, wsuri.port - else: - # If sock is given, host and port shouldn't be specified. - host, port = None, None - # If host and port are given, override values from the URI. - host = kwargs.pop("host", host) - port = kwargs.pop("port", port) - create_connection = functools.partial( - loop.create_connection, factory, host, port, **kwargs - ) - else: - create_connection = functools.partial( - loop.create_unix_connection, factory, path, **kwargs - ) - - # This is a coroutine function. - self._create_connection = create_connection - self._wsuri = wsuri - - def handle_redirect(self, uri: str) -> None: - # Update the state of this instance to connect to a new URI. - old_wsuri = self._wsuri - new_wsuri = parse_uri(uri) - - # Forbid TLS downgrade. - if old_wsuri.secure and not new_wsuri.secure: - raise SecurityError("redirect from WSS to WS") - - same_origin = ( - old_wsuri.host == new_wsuri.host and old_wsuri.port == new_wsuri.port - ) - - # Rewrite the host and port arguments for cross-origin redirects. - # This preserves connection overrides with the host and port - # arguments if the redirect points to the same host and port. - if not same_origin: - # Replace the host and port argument passed to the protocol factory. - factory = self._create_connection.args[0] - factory = functools.partial( - factory.func, - *factory.args, - **dict(factory.keywords, host=new_wsuri.host, port=new_wsuri.port), - ) - # Replace the host and port argument passed to create_connection. - self._create_connection = functools.partial( - self._create_connection.func, - *(factory, new_wsuri.host, new_wsuri.port), - **self._create_connection.keywords, - ) - - # Set the new WebSocket URI. This suffices for same-origin redirects. - self._wsuri = new_wsuri - - # async with connect(...) - - async def __aenter__(self) -> WebSocketClientProtocol: - return await self - - async def __aexit__( - self, - exc_type: Optional[Type[BaseException]], - exc_value: Optional[BaseException], - traceback: Optional[TracebackType], - ) -> None: - await self.ws_client.close() - - # await connect(...) - - def __await__(self) -> Generator[Any, None, WebSocketClientProtocol]: - # Create a suitable iterator by calling __await__ on a coroutine. - return self.__await_impl__().__await__() - - async def __await_impl__(self) -> WebSocketClientProtocol: - for redirects in range(self.MAX_REDIRECTS_ALLOWED): - transport, protocol = await self._create_connection() - # https://github.com/python/typeshed/pull/2756 - transport = cast(asyncio.Transport, transport) - protocol = cast(WebSocketClientProtocol, protocol) - - try: - try: - await protocol.handshake( - self._wsuri, - origin=protocol.origin, - available_extensions=protocol.available_extensions, - available_subprotocols=protocol.available_subprotocols, - extra_headers=protocol.extra_headers, - ) - except Exception: - protocol.fail_connection() - await protocol.wait_closed() - raise - else: - self.ws_client = protocol - return protocol - except RedirectHandshake as exc: - self.handle_redirect(exc.uri) - else: - raise SecurityError("too many redirects") - - # yield from connect(...) - - __iter__ = __await__ - - -connect = Connect - - -def unix_connect(path: str, uri: str = "ws://localhost/", **kwargs: Any) -> Connect: - """ - Similar to :func:`connect`, but for connecting to a Unix socket. - - This function calls the event loop's - :meth:`~asyncio.loop.create_unix_connection` method. - - It is only available on Unix. + * ``extra_headers`` sets additional HTTP request headers – it can be a + mapping or an iterable of (name, value) pairs - It's mainly useful for debugging servers listening on Unix sockets. + :func:`connect` raises :exc:`~websockets.uri.InvalidURI` if ``uri`` is + invalid and :exc:`~websockets.handshake.InvalidHandshake` if the opening + handshake fails. - :param path: file system path to the Unix socket - :param uri: WebSocket URI + On Python 3.5, :func:`connect` can be used as a asynchronous context + manager. In that case, the connection is closed when exiting the context. """ - return connect(uri=uri, path=path, **kwargs) + if loop is None: + loop = asyncio.get_event_loop() + + # Backwards-compatibility: create_protocol used to be called klass. + # In the unlikely event that both are specified, klass is ignored. + if create_protocol is None: + create_protocol = klass + + if create_protocol is None: + create_protocol = WebSocketClientProtocol + + wsuri = parse_uri(uri) + if wsuri.secure: + kwds.setdefault('ssl', True) + elif kwds.get('ssl') is not None: + raise ValueError("connect() received a SSL context for a ws:// URI. " + "Use a wss:// URI to enable TLS.") + factory = lambda: create_protocol( + host=wsuri.host, port=wsuri.port, secure=wsuri.secure, + timeout=timeout, max_size=max_size, max_queue=max_queue, + read_limit=read_limit, write_limit=write_limit, + loop=loop, legacy_recv=legacy_recv, + ) + + transport, protocol = yield from loop.create_connection( + factory, wsuri.host, wsuri.port, **kwds) + + try: + yield from protocol.handshake( + wsuri, origin=origin, subprotocols=subprotocols, + extra_headers=extra_headers) + except Exception: + yield from protocol.close_connection(force=True) + raise + + return protocol + + +try: + from .py35.client import Connect +except (SyntaxError, ImportError): # pragma: no cover + pass +else: + Connect.__wrapped__ = connect + # Copy over docstring to support building documentation on Python 3.5. + Connect.__doc__ = connect.__doc__ + connect = Connect diff --git a/venv/Lib/site-packages/websockets/compatibility.py b/venv/Lib/site-packages/websockets/compatibility.py new file mode 100644 index 00000000..c8c30142 --- /dev/null +++ b/venv/Lib/site-packages/websockets/compatibility.py @@ -0,0 +1,48 @@ +import asyncio +import http + + +# Replace with BaseEventLoop.create_task when dropping Python < 3.4.2. +try: # pragma: no cover + asyncio_ensure_future = asyncio.ensure_future # Python ≥ 3.5 +except AttributeError: # pragma: no cover + asyncio_ensure_future = asyncio.async # Python < 3.5 + +try: # pragma: no cover + # Python ≥ 3.5 + SWITCHING_PROTOCOLS = http.HTTPStatus.SWITCHING_PROTOCOLS + OK = http.HTTPStatus.OK + BAD_REQUEST = http.HTTPStatus.BAD_REQUEST + UNAUTHORIZED = http.HTTPStatus.UNAUTHORIZED + FORBIDDEN = http.HTTPStatus.FORBIDDEN + INTERNAL_SERVER_ERROR = http.HTTPStatus.INTERNAL_SERVER_ERROR + SERVICE_UNAVAILABLE = http.HTTPStatus.SERVICE_UNAVAILABLE +except AttributeError: # pragma: no cover + # Python < 3.5 + class SWITCHING_PROTOCOLS: + value = 101 + phrase = "Switching Protocols" + + class OK: + value = 200 + phrase = "OK" + + class BAD_REQUEST: + value = 400 + phrase = "Bad Request" + + class UNAUTHORIZED: + value = 401 + phrase = "Unauthorized" + + class FORBIDDEN: + value = 403 + phrase = "Forbidden" + + class INTERNAL_SERVER_ERROR: + value = 500 + phrase = "Internal Server Error" + + class SERVICE_UNAVAILABLE: + value = 503 + phrase = "Service Unavailable" diff --git a/venv/Lib/site-packages/websockets/exceptions.py b/venv/Lib/site-packages/websockets/exceptions.py index 9873a171..3db56956 100644 --- a/venv/Lib/site-packages/websockets/exceptions.py +++ b/venv/Lib/site-packages/websockets/exceptions.py @@ -1,366 +1,95 @@ -""" -:mod:`websockets.exceptions` defines the following exception hierarchy: - -* :exc:`WebSocketException` - * :exc:`ConnectionClosed` - * :exc:`ConnectionClosedError` - * :exc:`ConnectionClosedOK` - * :exc:`InvalidHandshake` - * :exc:`SecurityError` - * :exc:`InvalidMessage` - * :exc:`InvalidHeader` - * :exc:`InvalidHeaderFormat` - * :exc:`InvalidHeaderValue` - * :exc:`InvalidOrigin` - * :exc:`InvalidUpgrade` - * :exc:`InvalidStatusCode` - * :exc:`NegotiationError` - * :exc:`DuplicateParameter` - * :exc:`InvalidParameterName` - * :exc:`InvalidParameterValue` - * :exc:`AbortHandshake` - * :exc:`RedirectHandshake` - * :exc:`InvalidState` - * :exc:`InvalidURI` - * :exc:`PayloadTooBig` - * :exc:`ProtocolError` - -""" - -import http -from typing import Optional - -from .http import Headers, HeadersLike - - __all__ = [ - "WebSocketException", - "ConnectionClosed", - "ConnectionClosedError", - "ConnectionClosedOK", - "InvalidHandshake", - "SecurityError", - "InvalidMessage", - "InvalidHeader", - "InvalidHeaderFormat", - "InvalidHeaderValue", - "InvalidOrigin", - "InvalidUpgrade", - "InvalidStatusCode", - "NegotiationError", - "DuplicateParameter", - "InvalidParameterName", - "InvalidParameterValue", - "AbortHandshake", - "RedirectHandshake", - "InvalidState", - "InvalidURI", - "PayloadTooBig", - "ProtocolError", - "WebSocketProtocolError", + 'AbortHandshake', 'InvalidHandshake', 'InvalidMessage', 'InvalidOrigin', + 'InvalidState', 'InvalidStatusCode', 'InvalidURI', 'ConnectionClosed', + 'PayloadTooBig', 'WebSocketProtocolError', ] -class WebSocketException(Exception): - """ - Base class for all exceptions defined by :mod:`websockets`. - - """ - - -CLOSE_CODES = { - 1000: "OK", - 1001: "going away", - 1002: "protocol error", - 1003: "unsupported type", - # 1004 is reserved - 1005: "no status code [internal]", - 1006: "connection closed abnormally [internal]", - 1007: "invalid data", - 1008: "policy violation", - 1009: "message too big", - 1010: "extension required", - 1011: "unexpected error", - 1015: "TLS failure [internal]", -} - - -def format_close(code: int, reason: str) -> str: - """ - Display a human-readable version of the close code and reason. - - """ - if 3000 <= code < 4000: - explanation = "registered" - elif 4000 <= code < 5000: - explanation = "private use" - else: - explanation = CLOSE_CODES.get(code, "unknown") - result = f"code = {code} ({explanation}), " - - if reason: - result += f"reason = {reason}" - else: - result += "no reason" - - return result - - -class ConnectionClosed(WebSocketException): - """ - Raised when trying to interact with a closed connection. - - Provides the connection close code and reason in its ``code`` and - ``reason`` attributes respectively. - - """ - - def __init__(self, code: int, reason: str) -> None: - self.code = code - self.reason = reason - super().__init__(format_close(code, reason)) - - -class ConnectionClosedError(ConnectionClosed): - """ - Like :exc:`ConnectionClosed`, when the connection terminated with an error. - - This means the close code is different from 1000 (OK) and 1001 (going away). - - """ - - def __init__(self, code: int, reason: str) -> None: - assert code != 1000 and code != 1001 - super().__init__(code, reason) - - -class ConnectionClosedOK(ConnectionClosed): - """ - Like :exc:`ConnectionClosed`, when the connection terminated properly. - - This means the close code is 1000 (OK) or 1001 (going away). - +class InvalidHandshake(Exception): """ + Exception raised when a handshake request or response is invalid. - def __init__(self, code: int, reason: str) -> None: - assert code == 1000 or code == 1001 - super().__init__(code, reason) - - -class InvalidHandshake(WebSocketException): """ - Raised during the handshake when the WebSocket connection fails. - """ - -class SecurityError(InvalidHandshake): +class AbortHandshake(InvalidHandshake): """ - Raised when a handshake request or response breaks a security rule. - - Security limits are hard coded. + Exception raised to abort a handshake and return a HTTP response. """ + def __init__(self, status, headers, body=None): + self.status = status + self.headers = headers + self.body = body class InvalidMessage(InvalidHandshake): """ - Raised when a handshake request or response is malformed. - - """ - - -class InvalidHeader(InvalidHandshake): - """ - Raised when a HTTP header doesn't have a valid format or value. + Exception raised when the HTTP message in a handshake request is malformed. """ - def __init__(self, name: str, value: Optional[str] = None) -> None: - self.name = name - self.value = value - if value is None: - message = f"missing {name} header" - elif value == "": - message = f"empty {name} header" - else: - message = f"invalid {name} header: {value}" - super().__init__(message) - -class InvalidHeaderFormat(InvalidHeader): +class InvalidOrigin(InvalidHandshake): """ - Raised when a HTTP header cannot be parsed. - - The format of the header doesn't match the grammar for that header. - - """ - - def __init__(self, name: str, error: str, header: str, pos: int) -> None: - self.name = name - error = f"{error} at {pos} in {header}" - super().__init__(name, error) - - -class InvalidHeaderValue(InvalidHeader): - """ - Raised when a HTTP header has a wrong value. - - The format of the header is correct but a value isn't acceptable. - - """ - - -class InvalidOrigin(InvalidHeader): - """ - Raised when the Origin header in a request isn't allowed. - - """ - - def __init__(self, origin: Optional[str]) -> None: - super().__init__("Origin", origin) - - -class InvalidUpgrade(InvalidHeader): - """ - Raised when the Upgrade or Connection header isn't correct. + Exception raised when the origin in a handshake request is forbidden. """ class InvalidStatusCode(InvalidHandshake): """ - Raised when a handshake response status code is invalid. + Exception raised when a handshake response status code is invalid. - The integer status code is available in the ``status_code`` attribute. + Provides the integer status code in its ``status_code`` attribute. """ - - def __init__(self, status_code: int) -> None: + def __init__(self, status_code): self.status_code = status_code - message = f"server rejected WebSocket connection: HTTP {status_code}" - super().__init__(message) - - -class NegotiationError(InvalidHandshake): - """ - Raised when negotiating an extension fails. - - """ - - -class DuplicateParameter(NegotiationError): - """ - Raised when a parameter name is repeated in an extension header. - - """ - - def __init__(self, name: str) -> None: - self.name = name - message = f"duplicate parameter: {name}" + message = 'Status code not 101: {}'.format(status_code) super().__init__(message) -class InvalidParameterName(NegotiationError): +class InvalidState(Exception): """ - Raised when a parameter name in an extension header is invalid. + Exception raised when an operation is forbidden in the current state. """ - def __init__(self, name: str) -> None: - self.name = name - message = f"invalid parameter name: {name}" - super().__init__(message) - - -class InvalidParameterValue(NegotiationError): - """ - Raised when a parameter value in an extension header is invalid. +class ConnectionClosed(InvalidState): """ + Exception raised when trying to read or write on a closed connection. - def __init__(self, name: str, value: Optional[str]) -> None: - self.name = name - self.value = value - if value is None: - message = f"missing value for parameter {name}" - elif value == "": - message = f"empty value for parameter {name}" - else: - message = f"invalid value for parameter {name}: {value}" - super().__init__(message) - - -class AbortHandshake(InvalidHandshake): - """ - Raised to abort the handshake on purpose and return a HTTP response. - - This exception is an implementation detail. - - The public API is :meth:`~server.WebSocketServerProtocol.process_request`. + Provides the connection close code and reason in its ``code`` and + ``reason`` attributes respectively. """ - - def __init__( - self, status: http.HTTPStatus, headers: HeadersLike, body: bytes = b"" - ) -> None: - self.status = status - self.headers = Headers(headers) - self.body = body - message = f"HTTP {status}, {len(self.headers)} headers, {len(body)} bytes" + def __init__(self, code, reason): + self.code = code + self.reason = reason + message = 'WebSocket connection is closed: ' + message += 'code = {}, '.format(code) if code else 'no code, ' + message += 'reason = {}.'.format(reason) if reason else 'no reason.' super().__init__(message) -class RedirectHandshake(InvalidHandshake): +class InvalidURI(Exception): """ - Raised when a handshake gets redirected. - - This exception is an implementation detail. + Exception raised when an URI isn't a valid websocket URI. """ - def __init__(self, uri: str) -> None: - self.uri = uri - - def __str__(self) -> str: - return f"redirect to {self.uri}" - -class InvalidState(WebSocketException, AssertionError): +class PayloadTooBig(Exception): """ - Raised when an operation is forbidden in the current state. - - This exception is an implementation detail. - - It should never be raised in normal circumstances. + Exception raised when a frame's payload exceeds the maximum size. """ -class InvalidURI(WebSocketException): +class WebSocketProtocolError(Exception): """ - Raised when connecting to an URI that isn't a valid WebSocket URI. + Internal exception raised when the remote side breaks the protocol. """ - - def __init__(self, uri: str) -> None: - self.uri = uri - message = "{} isn't a valid URI".format(uri) - super().__init__(message) - - -class PayloadTooBig(WebSocketException): - """ - Raised when receiving a frame with a payload exceeding the maximum size. - - """ - - -class ProtocolError(WebSocketException): - """ - Raised when the other side breaks the protocol. - - """ - - -WebSocketProtocolError = ProtocolError # for backwards compatibility diff --git a/venv/Lib/site-packages/websockets/extensions/base.py b/venv/Lib/site-packages/websockets/extensions/base.py deleted file mode 100644 index aa52a7ad..00000000 --- a/venv/Lib/site-packages/websockets/extensions/base.py +++ /dev/null @@ -1,119 +0,0 @@ -""" -:mod:`websockets.extensions.base` defines abstract classes for implementing -extensions. - -See `section 9 of RFC 6455`_. - -.. _section 9 of RFC 6455: http://tools.ietf.org/html/rfc6455#section-9 - -""" - -from typing import List, Optional, Sequence, Tuple - -from ..framing import Frame -from ..typing import ExtensionName, ExtensionParameter - - -__all__ = ["Extension", "ClientExtensionFactory", "ServerExtensionFactory"] - - -class Extension: - """ - Abstract class for extensions. - - """ - - @property - def name(self) -> ExtensionName: - """ - Extension identifier. - - """ - - def decode(self, frame: Frame, *, max_size: Optional[int] = None) -> Frame: - """ - Decode an incoming frame. - - :param frame: incoming frame - :param max_size: maximum payload size in bytes - - """ - - def encode(self, frame: Frame) -> Frame: - """ - Encode an outgoing frame. - - :param frame: outgoing frame - - """ - - -class ClientExtensionFactory: - """ - Abstract class for client-side extension factories. - - """ - - @property - def name(self) -> ExtensionName: - """ - Extension identifier. - - """ - - def get_request_params(self) -> List[ExtensionParameter]: - """ - Build request parameters. - - Return a list of ``(name, value)`` pairs. - - """ - - def process_response_params( - self, - params: Sequence[ExtensionParameter], - accepted_extensions: Sequence[Extension], - ) -> Extension: - """ - Process response parameters received from the server. - - :param params: list of ``(name, value)`` pairs. - :param accepted_extensions: list of previously accepted extensions. - :raises ~websockets.exceptions.NegotiationError: if parameters aren't - acceptable - - """ - - -class ServerExtensionFactory: - """ - Abstract class for server-side extension factories. - - """ - - @property - def name(self) -> ExtensionName: - """ - Extension identifier. - - """ - - def process_request_params( - self, - params: Sequence[ExtensionParameter], - accepted_extensions: Sequence[Extension], - ) -> Tuple[List[ExtensionParameter], Extension]: - """ - Process request parameters received from the client. - - To accept the offer, return a 2-uple containing: - - - response parameters: a list of ``(name, value)`` pairs - - an extension: an instance of a subclass of :class:`Extension` - - :param params: list of ``(name, value)`` pairs. - :param accepted_extensions: list of previously accepted extensions. - :raises ~websockets.exceptions.NegotiationError: to reject the offer, - if parameters aren't acceptable - - """ diff --git a/venv/Lib/site-packages/websockets/extensions/permessage_deflate.py b/venv/Lib/site-packages/websockets/extensions/permessage_deflate.py deleted file mode 100644 index e38d9eda..00000000 --- a/venv/Lib/site-packages/websockets/extensions/permessage_deflate.py +++ /dev/null @@ -1,588 +0,0 @@ -""" -:mod:`websockets.extensions.permessage_deflate` implements the Compression -Extensions for WebSocket as specified in :rfc:`7692`. - -""" - -import zlib -from typing import Any, Dict, List, Optional, Sequence, Tuple, Union - -from ..exceptions import ( - DuplicateParameter, - InvalidParameterName, - InvalidParameterValue, - NegotiationError, - PayloadTooBig, -) -from ..framing import CTRL_OPCODES, OP_CONT, Frame -from ..typing import ExtensionName, ExtensionParameter -from .base import ClientExtensionFactory, Extension, ServerExtensionFactory - - -__all__ = [ - "PerMessageDeflate", - "ClientPerMessageDeflateFactory", - "ServerPerMessageDeflateFactory", -] - -_EMPTY_UNCOMPRESSED_BLOCK = b"\x00\x00\xff\xff" - -_MAX_WINDOW_BITS_VALUES = [str(bits) for bits in range(8, 16)] - - -class PerMessageDeflate(Extension): - """ - Per-Message Deflate extension. - - """ - - name = ExtensionName("permessage-deflate") - - def __init__( - self, - remote_no_context_takeover: bool, - local_no_context_takeover: bool, - remote_max_window_bits: int, - local_max_window_bits: int, - compress_settings: Optional[Dict[Any, Any]] = None, - ) -> None: - """ - Configure the Per-Message Deflate extension. - - """ - if compress_settings is None: - compress_settings = {} - - assert remote_no_context_takeover in [False, True] - assert local_no_context_takeover in [False, True] - assert 8 <= remote_max_window_bits <= 15 - assert 8 <= local_max_window_bits <= 15 - assert "wbits" not in compress_settings - - self.remote_no_context_takeover = remote_no_context_takeover - self.local_no_context_takeover = local_no_context_takeover - self.remote_max_window_bits = remote_max_window_bits - self.local_max_window_bits = local_max_window_bits - self.compress_settings = compress_settings - - if not self.remote_no_context_takeover: - self.decoder = zlib.decompressobj(wbits=-self.remote_max_window_bits) - - if not self.local_no_context_takeover: - self.encoder = zlib.compressobj( - wbits=-self.local_max_window_bits, **self.compress_settings - ) - - # To handle continuation frames properly, we must keep track of - # whether that initial frame was encoded. - self.decode_cont_data = False - # There's no need for self.encode_cont_data because we always encode - # outgoing frames, so it would always be True. - - def __repr__(self) -> str: - return ( - f"PerMessageDeflate(" - f"remote_no_context_takeover={self.remote_no_context_takeover}, " - f"local_no_context_takeover={self.local_no_context_takeover}, " - f"remote_max_window_bits={self.remote_max_window_bits}, " - f"local_max_window_bits={self.local_max_window_bits})" - ) - - def decode(self, frame: Frame, *, max_size: Optional[int] = None) -> Frame: - """ - Decode an incoming frame. - - """ - # Skip control frames. - if frame.opcode in CTRL_OPCODES: - return frame - - # Handle continuation data frames: - # - skip if the initial data frame wasn't encoded - # - reset "decode continuation data" flag if it's a final frame - if frame.opcode == OP_CONT: - if not self.decode_cont_data: - return frame - if frame.fin: - self.decode_cont_data = False - - # Handle text and binary data frames: - # - skip if the frame isn't encoded - # - set "decode continuation data" flag if it's a non-final frame - else: - if not frame.rsv1: - return frame - if not frame.fin: # frame.rsv1 is True at this point - self.decode_cont_data = True - - # Re-initialize per-message decoder. - if self.remote_no_context_takeover: - self.decoder = zlib.decompressobj(wbits=-self.remote_max_window_bits) - - # Uncompress compressed frames. Protect against zip bombs by - # preventing zlib from decompressing more than max_length bytes - # (except when the limit is disabled with max_size = None). - data = frame.data - if frame.fin: - data += _EMPTY_UNCOMPRESSED_BLOCK - max_length = 0 if max_size is None else max_size - data = self.decoder.decompress(data, max_length) - if self.decoder.unconsumed_tail: - raise PayloadTooBig( - f"Uncompressed payload length exceeds size limit (? > {max_size} bytes)" - ) - - # Allow garbage collection of the decoder if it won't be reused. - if frame.fin and self.remote_no_context_takeover: - del self.decoder - - return frame._replace(data=data, rsv1=False) - - def encode(self, frame: Frame) -> Frame: - """ - Encode an outgoing frame. - - """ - # Skip control frames. - if frame.opcode in CTRL_OPCODES: - return frame - - # Since we always encode and never fragment messages, there's no logic - # similar to decode() here at this time. - - if frame.opcode != OP_CONT: - # Re-initialize per-message decoder. - if self.local_no_context_takeover: - self.encoder = zlib.compressobj( - wbits=-self.local_max_window_bits, **self.compress_settings - ) - - # Compress data frames. - data = self.encoder.compress(frame.data) + self.encoder.flush(zlib.Z_SYNC_FLUSH) - if frame.fin and data.endswith(_EMPTY_UNCOMPRESSED_BLOCK): - data = data[:-4] - - # Allow garbage collection of the encoder if it won't be reused. - if frame.fin and self.local_no_context_takeover: - del self.encoder - - return frame._replace(data=data, rsv1=True) - - -def _build_parameters( - server_no_context_takeover: bool, - client_no_context_takeover: bool, - server_max_window_bits: Optional[int], - client_max_window_bits: Optional[Union[int, bool]], -) -> List[ExtensionParameter]: - """ - Build a list of ``(name, value)`` pairs for some compression parameters. - - """ - params: List[ExtensionParameter] = [] - if server_no_context_takeover: - params.append(("server_no_context_takeover", None)) - if client_no_context_takeover: - params.append(("client_no_context_takeover", None)) - if server_max_window_bits: - params.append(("server_max_window_bits", str(server_max_window_bits))) - if client_max_window_bits is True: # only in handshake requests - params.append(("client_max_window_bits", None)) - elif client_max_window_bits: - params.append(("client_max_window_bits", str(client_max_window_bits))) - return params - - -def _extract_parameters( - params: Sequence[ExtensionParameter], *, is_server: bool -) -> Tuple[bool, bool, Optional[int], Optional[Union[int, bool]]]: - """ - Extract compression parameters from a list of ``(name, value)`` pairs. - - If ``is_server`` is ``True``, ``client_max_window_bits`` may be provided - without a value. This is only allow in handshake requests. - - """ - server_no_context_takeover: bool = False - client_no_context_takeover: bool = False - server_max_window_bits: Optional[int] = None - client_max_window_bits: Optional[Union[int, bool]] = None - - for name, value in params: - - if name == "server_no_context_takeover": - if server_no_context_takeover: - raise DuplicateParameter(name) - if value is None: - server_no_context_takeover = True - else: - raise InvalidParameterValue(name, value) - - elif name == "client_no_context_takeover": - if client_no_context_takeover: - raise DuplicateParameter(name) - if value is None: - client_no_context_takeover = True - else: - raise InvalidParameterValue(name, value) - - elif name == "server_max_window_bits": - if server_max_window_bits is not None: - raise DuplicateParameter(name) - if value in _MAX_WINDOW_BITS_VALUES: - server_max_window_bits = int(value) - else: - raise InvalidParameterValue(name, value) - - elif name == "client_max_window_bits": - if client_max_window_bits is not None: - raise DuplicateParameter(name) - if is_server and value is None: # only in handshake requests - client_max_window_bits = True - elif value in _MAX_WINDOW_BITS_VALUES: - client_max_window_bits = int(value) - else: - raise InvalidParameterValue(name, value) - - else: - raise InvalidParameterName(name) - - return ( - server_no_context_takeover, - client_no_context_takeover, - server_max_window_bits, - client_max_window_bits, - ) - - -class ClientPerMessageDeflateFactory(ClientExtensionFactory): - """ - Client-side extension factory for the Per-Message Deflate extension. - - Parameters behave as described in `section 7.1 of RFC 7692`_. Set them to - ``True`` to include them in the negotiation offer without a value or to an - integer value to include them with this value. - - .. _section 7.1 of RFC 7692: https://tools.ietf.org/html/rfc7692#section-7.1 - - :param server_no_context_takeover: defaults to ``False`` - :param client_no_context_takeover: defaults to ``False`` - :param server_max_window_bits: optional, defaults to ``None`` - :param client_max_window_bits: optional, defaults to ``None`` - :param compress_settings: optional, keyword arguments for - :func:`zlib.compressobj`, excluding ``wbits`` - - """ - - name = ExtensionName("permessage-deflate") - - def __init__( - self, - server_no_context_takeover: bool = False, - client_no_context_takeover: bool = False, - server_max_window_bits: Optional[int] = None, - client_max_window_bits: Optional[Union[int, bool]] = None, - compress_settings: Optional[Dict[str, Any]] = None, - ) -> None: - """ - Configure the Per-Message Deflate extension factory. - - """ - if not (server_max_window_bits is None or 8 <= server_max_window_bits <= 15): - raise ValueError("server_max_window_bits must be between 8 and 15") - if not ( - client_max_window_bits is None - or client_max_window_bits is True - or 8 <= client_max_window_bits <= 15 - ): - raise ValueError("client_max_window_bits must be between 8 and 15") - if compress_settings is not None and "wbits" in compress_settings: - raise ValueError( - "compress_settings must not include wbits, " - "set client_max_window_bits instead" - ) - - self.server_no_context_takeover = server_no_context_takeover - self.client_no_context_takeover = client_no_context_takeover - self.server_max_window_bits = server_max_window_bits - self.client_max_window_bits = client_max_window_bits - self.compress_settings = compress_settings - - def get_request_params(self) -> List[ExtensionParameter]: - """ - Build request parameters. - - """ - return _build_parameters( - self.server_no_context_takeover, - self.client_no_context_takeover, - self.server_max_window_bits, - self.client_max_window_bits, - ) - - def process_response_params( - self, - params: Sequence[ExtensionParameter], - accepted_extensions: Sequence["Extension"], - ) -> PerMessageDeflate: - """ - Process response parameters. - - Return an extension instance. - - """ - if any(other.name == self.name for other in accepted_extensions): - raise NegotiationError(f"received duplicate {self.name}") - - # Request parameters are available in instance variables. - - # Load response parameters in local variables. - ( - server_no_context_takeover, - client_no_context_takeover, - server_max_window_bits, - client_max_window_bits, - ) = _extract_parameters(params, is_server=False) - - # After comparing the request and the response, the final - # configuration must be available in the local variables. - - # server_no_context_takeover - # - # Req. Resp. Result - # ------ ------ -------------------------------------------------- - # False False False - # False True True - # True False Error! - # True True True - - if self.server_no_context_takeover: - if not server_no_context_takeover: - raise NegotiationError("expected server_no_context_takeover") - - # client_no_context_takeover - # - # Req. Resp. Result - # ------ ------ -------------------------------------------------- - # False False False - # False True True - # True False True - must change value - # True True True - - if self.client_no_context_takeover: - if not client_no_context_takeover: - client_no_context_takeover = True - - # server_max_window_bits - - # Req. Resp. Result - # ------ ------ -------------------------------------------------- - # None None None - # None 8≤M≤15 M - # 8≤N≤15 None Error! - # 8≤N≤15 8≤M≤N M - # 8≤N≤15 N self.server_max_window_bits: - raise NegotiationError("unsupported server_max_window_bits") - - # client_max_window_bits - - # Req. Resp. Result - # ------ ------ -------------------------------------------------- - # None None None - # None 8≤M≤15 Error! - # True None None - # True 8≤M≤15 M - # 8≤N≤15 None N - must change value - # 8≤N≤15 8≤M≤N M - # 8≤N≤15 N self.client_max_window_bits: - raise NegotiationError("unsupported client_max_window_bits") - - return PerMessageDeflate( - server_no_context_takeover, # remote_no_context_takeover - client_no_context_takeover, # local_no_context_takeover - server_max_window_bits or 15, # remote_max_window_bits - client_max_window_bits or 15, # local_max_window_bits - self.compress_settings, - ) - - -class ServerPerMessageDeflateFactory(ServerExtensionFactory): - """ - Server-side extension factory for the Per-Message Deflate extension. - - Parameters behave as described in `section 7.1 of RFC 7692`_. Set them to - ``True`` to include them in the negotiation offer without a value or to an - integer value to include them with this value. - - .. _section 7.1 of RFC 7692: https://tools.ietf.org/html/rfc7692#section-7.1 - - :param server_no_context_takeover: defaults to ``False`` - :param client_no_context_takeover: defaults to ``False`` - :param server_max_window_bits: optional, defaults to ``None`` - :param client_max_window_bits: optional, defaults to ``None`` - :param compress_settings: optional, keyword arguments for - :func:`zlib.compressobj`, excluding ``wbits`` - - """ - - name = ExtensionName("permessage-deflate") - - def __init__( - self, - server_no_context_takeover: bool = False, - client_no_context_takeover: bool = False, - server_max_window_bits: Optional[int] = None, - client_max_window_bits: Optional[int] = None, - compress_settings: Optional[Dict[str, Any]] = None, - ) -> None: - """ - Configure the Per-Message Deflate extension factory. - - """ - if not (server_max_window_bits is None or 8 <= server_max_window_bits <= 15): - raise ValueError("server_max_window_bits must be between 8 and 15") - if not (client_max_window_bits is None or 8 <= client_max_window_bits <= 15): - raise ValueError("client_max_window_bits must be between 8 and 15") - if compress_settings is not None and "wbits" in compress_settings: - raise ValueError( - "compress_settings must not include wbits, " - "set server_max_window_bits instead" - ) - - self.server_no_context_takeover = server_no_context_takeover - self.client_no_context_takeover = client_no_context_takeover - self.server_max_window_bits = server_max_window_bits - self.client_max_window_bits = client_max_window_bits - self.compress_settings = compress_settings - - def process_request_params( - self, - params: Sequence[ExtensionParameter], - accepted_extensions: Sequence["Extension"], - ) -> Tuple[List[ExtensionParameter], PerMessageDeflate]: - """ - Process request parameters. - - Return response params and an extension instance. - - """ - if any(other.name == self.name for other in accepted_extensions): - raise NegotiationError(f"skipped duplicate {self.name}") - - # Load request parameters in local variables. - ( - server_no_context_takeover, - client_no_context_takeover, - server_max_window_bits, - client_max_window_bits, - ) = _extract_parameters(params, is_server=True) - - # Configuration parameters are available in instance variables. - - # After comparing the request and the configuration, the response must - # be available in the local variables. - - # server_no_context_takeover - # - # Config Req. Resp. - # ------ ------ -------------------------------------------------- - # False False False - # False True True - # True False True - must change value to True - # True True True - - if self.server_no_context_takeover: - if not server_no_context_takeover: - server_no_context_takeover = True - - # client_no_context_takeover - # - # Config Req. Resp. - # ------ ------ -------------------------------------------------- - # False False False - # False True True (or False) - # True False True - must change value to True - # True True True (or False) - - if self.client_no_context_takeover: - if not client_no_context_takeover: - client_no_context_takeover = True - - # server_max_window_bits - - # Config Req. Resp. - # ------ ------ -------------------------------------------------- - # None None None - # None 8≤M≤15 M - # 8≤N≤15 None N - must change value - # 8≤N≤15 8≤M≤N M - # 8≤N≤15 N self.server_max_window_bits: - server_max_window_bits = self.server_max_window_bits - - # client_max_window_bits - - # Config Req. Resp. - # ------ ------ -------------------------------------------------- - # None None None - # None True None - must change value - # None 8≤M≤15 M (or None) - # 8≤N≤15 None Error! - # 8≤N≤15 True N - must change value - # 8≤N≤15 8≤M≤N M (or None) - # 8≤N≤15 N "Frame": - """ - Read a WebSocket frame. - - :param reader: coroutine that reads exactly the requested number of - bytes, unless the end of file is reached - :param mask: whether the frame should be masked i.e. whether the read - happens on the server side - :param max_size: maximum payload size in bytes - :param extensions: list of classes with a ``decode()`` method that - transforms the frame and return a new frame; extensions are applied - in reverse order - :raises ~websockets.exceptions.PayloadTooBig: if the frame exceeds - ``max_size`` - :raises ~websockets.exceptions.ProtocolError: if the frame - contains incorrect values - - """ - # Read the header. - data = await reader(2) - head1, head2 = struct.unpack("!BB", data) - - # While not Pythonic, this is marginally faster than calling bool(). - fin = True if head1 & 0b10000000 else False - rsv1 = True if head1 & 0b01000000 else False - rsv2 = True if head1 & 0b00100000 else False - rsv3 = True if head1 & 0b00010000 else False - opcode = head1 & 0b00001111 - - if (True if head2 & 0b10000000 else False) != mask: - raise ProtocolError("incorrect masking") - - length = head2 & 0b01111111 - if length == 126: - data = await reader(2) - (length,) = struct.unpack("!H", data) - elif length == 127: - data = await reader(8) - (length,) = struct.unpack("!Q", data) - if max_size is not None and length > max_size: - raise PayloadTooBig( - f"payload length exceeds size limit ({length} > {max_size} bytes)" - ) - if mask: - mask_bits = await reader(4) - - # Read the data. - data = await reader(length) - if mask: - data = apply_mask(data, mask_bits) - - frame = cls(fin, opcode, data, rsv1, rsv2, rsv3) - - if extensions is None: - extensions = [] - for extension in reversed(extensions): - frame = extension.decode(frame, max_size=max_size) - - frame.check() - - return frame - - def write( - frame, - write: Callable[[bytes], Any], - *, - mask: bool, - extensions: Optional[Sequence["websockets.extensions.base.Extension"]] = None, - ) -> None: - """ - Write a WebSocket frame. - - :param frame: frame to write - :param write: function that writes bytes - :param mask: whether the frame should be masked i.e. whether the write - happens on the client side - :param extensions: list of classes with an ``encode()`` method that - transform the frame and return a new frame; extensions are applied - in order - :raises ~websockets.exceptions.ProtocolError: if the frame - contains incorrect values - - """ - # The first parameter is called `frame` rather than `self`, - # but it's the instance of class to which this method is bound. - - frame.check() - - if extensions is None: - extensions = [] - for extension in extensions: - frame = extension.encode(frame) - - output = io.BytesIO() - - # Prepare the header. - head1 = ( - (0b10000000 if frame.fin else 0) - | (0b01000000 if frame.rsv1 else 0) - | (0b00100000 if frame.rsv2 else 0) - | (0b00010000 if frame.rsv3 else 0) - | frame.opcode - ) - - head2 = 0b10000000 if mask else 0 - - length = len(frame.data) - if length < 126: - output.write(struct.pack("!BB", head1, head2 | length)) - elif length < 65536: - output.write(struct.pack("!BBH", head1, head2 | 126, length)) - else: - output.write(struct.pack("!BBQ", head1, head2 | 127, length)) - - if mask: - mask_bits = struct.pack("!I", random.getrandbits(32)) - output.write(mask_bits) - - # Prepare the data. - if mask: - data = apply_mask(frame.data, mask_bits) - else: - data = frame.data - output.write(data) - - # Send the frame. - - # The frame is written in a single call to write in order to prevent - # TCP fragmentation. See #68 for details. This also makes it safe to - # send frames concurrently from multiple coroutines. - write(output.getvalue()) - - def check(frame) -> None: - """ - Check that reserved bits and opcode have acceptable values. - - :raises ~websockets.exceptions.ProtocolError: if a reserved - bit or the opcode is invalid - - """ - # The first parameter is called `frame` rather than `self`, - # but it's the instance of class to which this method is bound. - - if frame.rsv1 or frame.rsv2 or frame.rsv3: - raise ProtocolError("reserved bits must be 0") - - if frame.opcode in DATA_OPCODES: - return - elif frame.opcode in CTRL_OPCODES: - if len(frame.data) > 125: - raise ProtocolError("control frame too long") - if not frame.fin: - raise ProtocolError("fragmented control frame") - else: - raise ProtocolError(f"invalid opcode: {frame.opcode}") - - -def prepare_data(data: Data) -> Tuple[int, bytes]: + # Read the header + data = yield from reader(2) + head1, head2 = struct.unpack('!BB', data) + fin = bool(head1 & 0b10000000) + if head1 & 0b01110000: + raise WebSocketProtocolError("Reserved bits must be 0") + opcode = head1 & 0b00001111 + if bool(head2 & 0b10000000) != mask: + raise WebSocketProtocolError("Incorrect masking") + length = head2 & 0b01111111 + if length == 126: + data = yield from reader(2) + length, = struct.unpack('!H', data) + elif length == 127: + data = yield from reader(8) + length, = struct.unpack('!Q', data) + if max_size is not None and length > max_size: + raise PayloadTooBig("Payload exceeds limit " + "({} > {} bytes)".format(length, max_size)) + if mask: + mask_bits = yield from reader(4) + + # Read the data + data = yield from reader(length) + if mask: + data = apply_mask(data, mask_bits) + + frame = Frame(fin, opcode, data) + check_frame(frame) + return frame + + +def write_frame(frame, writer, mask): """ - Convert a string or byte-like object to an opcode and a bytes-like object. + Write a WebSocket frame. - This function is designed for data frames. + ``frame`` is the :class:`Frame` object to write. - If ``data`` is a :class:`str`, return ``OP_TEXT`` and a :class:`bytes` - object encoding ``data`` in UTF-8. + ``writer`` is a function accepting bytes. - If ``data`` is a bytes-like object, return ``OP_BINARY`` and a bytes-like - object. + ``mask`` is a :class:`bool` telling whether the frame should be masked + i.e. whether the write happens on the client side. - :raises TypeError: if ``data`` doesn't have a supported type + This function validates the frame before sending it and raises + :exc:`~websockets.exceptions.WebSocketProtocolError` if it contains + incorrect values. """ - if isinstance(data, str): - return OP_TEXT, data.encode("utf-8") - elif isinstance(data, (bytes, bytearray)): - return OP_BINARY, data - elif isinstance(data, memoryview): - if data.c_contiguous: - return OP_BINARY, data - else: - return OP_BINARY, data.tobytes() + check_frame(frame) + output = io.BytesIO() + + # Prepare the header + head1 = 0b10000000 if frame.fin else 0 + head1 |= frame.opcode + head2 = 0b10000000 if mask else 0 + length = len(frame.data) + if length < 0x7e: + output.write(struct.pack('!BB', head1, head2 | length)) + elif length < 0x10000: + output.write(struct.pack('!BBH', head1, head2 | 126, length)) else: - raise TypeError("data must be bytes-like or str") - - -def encode_data(data: Data) -> bytes: - """ - Convert a string or byte-like object to bytes. - - This function is designed for ping and pong frames. + output.write(struct.pack('!BBQ', head1, head2 | 127, length)) + if mask: + mask_bits = struct.pack('!I', random.getrandbits(32)) + output.write(mask_bits) + + # Prepare the data + if mask: + data = apply_mask(frame.data, mask_bits) + else: + data = frame.data + output.write(data) - If ``data`` is a :class:`str`, return a :class:`bytes` object encoding - ``data`` in UTF-8. + # Send the frame + writer(output.getvalue()) - If ``data`` is a bytes-like object, return a :class:`bytes` object. - :raises TypeError: if ``data`` doesn't have a supported type +def check_frame(frame): + """ + Raise :exc:`~websockets.exceptions.WebSocketProtocolError` if the frame + contains incorrect values. """ - if isinstance(data, str): - return data.encode("utf-8") - elif isinstance(data, (bytes, bytearray)): - return bytes(data) - elif isinstance(data, memoryview): - return data.tobytes() + if frame.opcode in (OP_CONT, OP_TEXT, OP_BINARY): + return + elif frame.opcode in (OP_CLOSE, OP_PING, OP_PONG): + if len(frame.data) > 125: + raise WebSocketProtocolError("Control frame too long") + if not frame.fin: + raise WebSocketProtocolError("Fragmented control frame") else: - raise TypeError("data must be bytes-like or str") + raise WebSocketProtocolError("Invalid opcode") -def parse_close(data: bytes) -> Tuple[int, str]: +def parse_close(data): """ - Parse the payload from a close frame. + Parse the data in a close frame. - Return ``(code, reason)``. + Return ``(code, reason)`` when ``code`` is an :class:`int` and ``reason`` + a :class:`str`. - :raises ~websockets.exceptions.ProtocolError: if data is ill-formed - :raises UnicodeDecodeError: if the reason isn't valid UTF-8 + Raise :exc:`~websockets.exceptions.WebSocketProtocolError` or + :exc:`UnicodeDecodeError` if the data is invalid. """ length = len(data) - if length >= 2: - (code,) = struct.unpack("!H", data[:2]) - check_close(code) - reason = data[2:].decode("utf-8") - return code, reason - elif length == 0: - return 1005, "" + if length == 0: + return 1005, '' + elif length == 1: + raise WebSocketProtocolError("Close frame too short") else: - assert length == 1 - raise ProtocolError("close frame too short") + code, = struct.unpack('!H', data[:2]) + if not (code in CLOSE_CODES or 3000 <= code < 5000): + raise WebSocketProtocolError("Invalid status code") + reason = data[2:].decode('utf-8') + return code, reason -def serialize_close(code: int, reason: str) -> bytes: +def serialize_close(code, reason): """ - Serialize the payload for a close frame. + Serialize the data for a close frame. This is the reverse of :func:`parse_close`. """ - check_close(code) - return struct.pack("!H", code) + reason.encode("utf-8") - - -def check_close(code: int) -> None: - """ - Check that the close code has an acceptable value for a close frame. - - :raises ~websockets.exceptions.ProtocolError: if the close code - is invalid - - """ - if not (code in EXTERNAL_CLOSE_CODES or 3000 <= code < 5000): - raise ProtocolError("invalid status code") - - -# at the bottom to allow circular import, because Extension depends on Frame -import websockets.extensions.base # isort:skip # noqa + return struct.pack('!H', code) + reason.encode('utf-8') diff --git a/venv/Lib/site-packages/websockets/handshake.py b/venv/Lib/site-packages/websockets/handshake.py index 9bfe2775..0b99242c 100644 --- a/venv/Lib/site-packages/websockets/handshake.py +++ b/venv/Lib/site-packages/websockets/handshake.py @@ -1,10 +1,19 @@ """ -:mod:`websockets.handshake` provides helpers for the WebSocket handshake. - -See `section 4 of RFC 6455`_. +The :mod:`websockets.handshake` module deals with the WebSocket opening +handshake according to `section 4 of RFC 6455`_. .. _section 4 of RFC 6455: http://tools.ietf.org/html/rfc6455#section-4 +It provides functions to implement the handshake with any existing HTTP +library. You must pass to these functions: + +- A ``set_header`` function accepting a header name and a header value, +- A ``get_header`` function accepting a header name and returning the header + value. + +The inputs and outputs of ``get_header`` and ``set_header`` are :class:`str` +objects containing only ASCII characters. + Some checks cannot be performed because they depend too much on the context; instead, they're documented below. @@ -26,160 +35,104 @@ To open a connection, a client must: """ import base64 -import binascii import hashlib import random -from typing import List -from .exceptions import InvalidHeader, InvalidHeaderValue, InvalidUpgrade -from .headers import ConnectionOption, UpgradeProtocol, parse_connection, parse_upgrade -from .http import Headers, MultipleValuesError +from .exceptions import InvalidHandshake -__all__ = ["build_request", "check_request", "build_response", "check_response"] +__all__ = [ + 'build_request', 'check_request', + 'build_response', 'check_response', +] GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" -def build_request(headers: Headers) -> str: +def build_request(set_header): """ Build a handshake request to send to the server. - Update request headers passed in argument. - - :param headers: request headers - :returns: ``key`` which must be passed to :func:`check_response` + Return the ``key`` which must be passed to :func:`check_response`. """ - raw_key = bytes(random.getrandbits(8) for _ in range(16)) - key = base64.b64encode(raw_key).decode() - headers["Upgrade"] = "websocket" - headers["Connection"] = "Upgrade" - headers["Sec-WebSocket-Key"] = key - headers["Sec-WebSocket-Version"] = "13" + rand = bytes(random.getrandbits(8) for _ in range(16)) + key = base64.b64encode(rand).decode() + set_header('Upgrade', 'WebSocket') + set_header('Connection', 'Upgrade') + set_header('Sec-WebSocket-Key', key) + set_header('Sec-WebSocket-Version', '13') return key -def check_request(headers: Headers) -> str: +def check_request(get_header): """ Check a handshake request received from the client. - This function doesn't verify that the request is an HTTP/1.1 or higher GET - request and doesn't perform ``Host`` and ``Origin`` checks. These controls - are usually performed earlier in the HTTP request handling code. They're - the responsibility of the caller. - - :param headers: request headers - :returns: ``key`` which must be passed to :func:`build_response` - :raises ~websockets.exceptions.InvalidHandshake: if the handshake request - is invalid; then the server must return 400 Bad Request error + If the handshake is valid, this function returns the ``key`` which must be + passed to :func:`build_response`. - """ - connection: List[ConnectionOption] = sum( - [parse_connection(value) for value in headers.get_all("Connection")], [] - ) + Otherwise it raises an :exc:`~websockets.exceptions.InvalidHandshake` + exception and the server must return an error like 400 Bad Request. - if not any(value.lower() == "upgrade" for value in connection): - raise InvalidUpgrade("Connection", ", ".join(connection)) - - upgrade: List[UpgradeProtocol] = sum( - [parse_upgrade(value) for value in headers.get_all("Upgrade")], [] - ) - - # For compatibility with non-strict implementations, ignore case when - # checking the Upgrade header. It's supposed to be 'WebSocket'. - if not (len(upgrade) == 1 and upgrade[0].lower() == "websocket"): - raise InvalidUpgrade("Upgrade", ", ".join(upgrade)) - - try: - s_w_key = headers["Sec-WebSocket-Key"] - except KeyError: - raise InvalidHeader("Sec-WebSocket-Key") - except MultipleValuesError: - raise InvalidHeader( - "Sec-WebSocket-Key", "more than one Sec-WebSocket-Key header found" - ) - - try: - raw_key = base64.b64decode(s_w_key.encode(), validate=True) - except binascii.Error: - raise InvalidHeaderValue("Sec-WebSocket-Key", s_w_key) - if len(raw_key) != 16: - raise InvalidHeaderValue("Sec-WebSocket-Key", s_w_key) + This function doesn't verify that the request is an HTTP/1.1 or higher GET + request and doesn't perform Host and Origin checks. These controls are + usually performed earlier in the HTTP request handling code. They're the + responsibility of the caller. + """ try: - s_w_version = headers["Sec-WebSocket-Version"] - except KeyError: - raise InvalidHeader("Sec-WebSocket-Version") - except MultipleValuesError: - raise InvalidHeader( - "Sec-WebSocket-Version", "more than one Sec-WebSocket-Version header found" - ) - - if s_w_version != "13": - raise InvalidHeaderValue("Sec-WebSocket-Version", s_w_version) - - return s_w_key - - -def build_response(headers: Headers, key: str) -> None: + assert get_header('Upgrade').lower() == 'websocket' + assert any( + token.strip() == 'upgrade' + for token in get_header('Connection').lower().split(',')) + key = get_header('Sec-WebSocket-Key') + assert len(base64.b64decode(key.encode(), validate=True)) == 16 + assert get_header('Sec-WebSocket-Version') == '13' + except Exception as exc: + raise InvalidHandshake("Invalid request") from exc + else: + return key + + +def build_response(set_header, key): """ Build a handshake response to send to the client. - Update response headers passed in argument. - - :param headers: response headers - :param key: comes from :func:`check_request` + ``key`` comes from :func:`check_request`. """ - headers["Upgrade"] = "websocket" - headers["Connection"] = "Upgrade" - headers["Sec-WebSocket-Accept"] = accept(key) + set_header('Upgrade', 'WebSocket') + set_header('Connection', 'Upgrade') + set_header('Sec-WebSocket-Accept', accept(key)) -def check_response(headers: Headers, key: str) -> None: +def check_response(get_header, key): """ Check a handshake response received from the server. + ``key`` comes from :func:`build_request`. + + If the handshake is valid, this function returns ``None``. + + Otherwise it raises an :exc:`~websockets.exceptions.InvalidHandshake` + exception. + This function doesn't verify that the response is an HTTP/1.1 or higher response with a 101 status code. These controls are the responsibility of the caller. - :param headers: response headers - :param key: comes from :func:`build_request` - :raises ~websockets.exceptions.InvalidHandshake: if the handshake response - is invalid - """ - connection: List[ConnectionOption] = sum( - [parse_connection(value) for value in headers.get_all("Connection")], [] - ) - - if not any(value.lower() == "upgrade" for value in connection): - raise InvalidUpgrade("Connection", " ".join(connection)) - - upgrade: List[UpgradeProtocol] = sum( - [parse_upgrade(value) for value in headers.get_all("Upgrade")], [] - ) - - # For compatibility with non-strict implementations, ignore case when - # checking the Upgrade header. It's supposed to be 'WebSocket'. - if not (len(upgrade) == 1 and upgrade[0].lower() == "websocket"): - raise InvalidUpgrade("Upgrade", ", ".join(upgrade)) - try: - s_w_accept = headers["Sec-WebSocket-Accept"] - except KeyError: - raise InvalidHeader("Sec-WebSocket-Accept") - except MultipleValuesError: - raise InvalidHeader( - "Sec-WebSocket-Accept", "more than one Sec-WebSocket-Accept header found" - ) - - if s_w_accept != accept(key): - raise InvalidHeaderValue("Sec-WebSocket-Accept", s_w_accept) + assert get_header('Upgrade').lower() == 'websocket' + assert any( + token.strip() == 'upgrade' + for token in get_header('Connection').lower().split(',')) + assert get_header('Sec-WebSocket-Accept') == accept(key) + except Exception as exc: + raise InvalidHandshake("Invalid response") from exc -def accept(key: str) -> str: +def accept(key): sha1 = hashlib.sha1((key + GUID).encode()).digest() return base64.b64encode(sha1).decode() diff --git a/venv/Lib/site-packages/websockets/headers.py b/venv/Lib/site-packages/websockets/headers.py deleted file mode 100644 index f33c94c0..00000000 --- a/venv/Lib/site-packages/websockets/headers.py +++ /dev/null @@ -1,515 +0,0 @@ -""" -:mod:`websockets.headers` provides parsers and serializers for HTTP headers -used in WebSocket handshake messages. - -These APIs cannot be imported from :mod:`websockets`. They must be imported -from :mod:`websockets.headers`. - -""" - -import base64 -import binascii -import re -from typing import Callable, List, NewType, Optional, Sequence, Tuple, TypeVar, cast - -from .exceptions import InvalidHeaderFormat, InvalidHeaderValue -from .typing import ExtensionHeader, ExtensionName, ExtensionParameter, Subprotocol - - -__all__ = [ - "parse_connection", - "parse_upgrade", - "parse_extension", - "build_extension", - "parse_subprotocol", - "build_subprotocol", - "build_www_authenticate_basic", - "parse_authorization_basic", - "build_authorization_basic", -] - - -T = TypeVar("T") - -ConnectionOption = NewType("ConnectionOption", str) -UpgradeProtocol = NewType("UpgradeProtocol", str) - - -# To avoid a dependency on a parsing library, we implement manually the ABNF -# described in https://tools.ietf.org/html/rfc6455#section-9.1 with the -# definitions from https://tools.ietf.org/html/rfc7230#appendix-B. - - -def peek_ahead(header: str, pos: int) -> Optional[str]: - """ - Return the next character from ``header`` at the given position. - - Return ``None`` at the end of ``header``. - - We never need to peek more than one character ahead. - - """ - return None if pos == len(header) else header[pos] - - -_OWS_re = re.compile(r"[\t ]*") - - -def parse_OWS(header: str, pos: int) -> int: - """ - Parse optional whitespace from ``header`` at the given position. - - Return the new position. - - The whitespace itself isn't returned because it isn't significant. - - """ - # There's always a match, possibly empty, whose content doesn't matter. - match = _OWS_re.match(header, pos) - assert match is not None - return match.end() - - -_token_re = re.compile(r"[-!#$%&\'*+.^_`|~0-9a-zA-Z]+") - - -def parse_token(header: str, pos: int, header_name: str) -> Tuple[str, int]: - """ - Parse a token from ``header`` at the given position. - - Return the token value and the new position. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - match = _token_re.match(header, pos) - if match is None: - raise InvalidHeaderFormat(header_name, "expected token", header, pos) - return match.group(), match.end() - - -_quoted_string_re = re.compile( - r'"(?:[\x09\x20-\x21\x23-\x5b\x5d-\x7e]|\\[\x09\x20-\x7e\x80-\xff])*"' -) - - -_unquote_re = re.compile(r"\\([\x09\x20-\x7e\x80-\xff])") - - -def parse_quoted_string(header: str, pos: int, header_name: str) -> Tuple[str, int]: - """ - Parse a quoted string from ``header`` at the given position. - - Return the unquoted value and the new position. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - match = _quoted_string_re.match(header, pos) - if match is None: - raise InvalidHeaderFormat(header_name, "expected quoted string", header, pos) - return _unquote_re.sub(r"\1", match.group()[1:-1]), match.end() - - -_quotable_re = re.compile(r"[\x09\x20-\x7e\x80-\xff]*") - - -_quote_re = re.compile(r"([\x22\x5c])") - - -def build_quoted_string(value: str) -> str: - """ - Format ``value`` as a quoted string. - - This is the reverse of :func:`parse_quoted_string`. - - """ - match = _quotable_re.fullmatch(value) - if match is None: - raise ValueError("invalid characters for quoted-string encoding") - return '"' + _quote_re.sub(r"\\\1", value) + '"' - - -def parse_list( - parse_item: Callable[[str, int, str], Tuple[T, int]], - header: str, - pos: int, - header_name: str, -) -> List[T]: - """ - Parse a comma-separated list from ``header`` at the given position. - - This is appropriate for parsing values with the following grammar: - - 1#item - - ``parse_item`` parses one item. - - ``header`` is assumed not to start or end with whitespace. - - (This function is designed for parsing an entire header value and - :func:`~websockets.http.read_headers` strips whitespace from values.) - - Return a list of items. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - # Per https://tools.ietf.org/html/rfc7230#section-7, "a recipient MUST - # parse and ignore a reasonable number of empty list elements"; hence - # while loops that remove extra delimiters. - - # Remove extra delimiters before the first item. - while peek_ahead(header, pos) == ",": - pos = parse_OWS(header, pos + 1) - - items = [] - while True: - # Loop invariant: a item starts at pos in header. - item, pos = parse_item(header, pos, header_name) - items.append(item) - pos = parse_OWS(header, pos) - - # We may have reached the end of the header. - if pos == len(header): - break - - # There must be a delimiter after each element except the last one. - if peek_ahead(header, pos) == ",": - pos = parse_OWS(header, pos + 1) - else: - raise InvalidHeaderFormat(header_name, "expected comma", header, pos) - - # Remove extra delimiters before the next item. - while peek_ahead(header, pos) == ",": - pos = parse_OWS(header, pos + 1) - - # We may have reached the end of the header. - if pos == len(header): - break - - # Since we only advance in the header by one character with peek_ahead() - # or with the end position of a regex match, we can't overshoot the end. - assert pos == len(header) - - return items - - -def parse_connection_option( - header: str, pos: int, header_name: str -) -> Tuple[ConnectionOption, int]: - """ - Parse a Connection option from ``header`` at the given position. - - Return the protocol value and the new position. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - item, pos = parse_token(header, pos, header_name) - return cast(ConnectionOption, item), pos - - -def parse_connection(header: str) -> List[ConnectionOption]: - """ - Parse a ``Connection`` header. - - Return a list of HTTP connection options. - - :param header: value of the ``Connection`` header - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - return parse_list(parse_connection_option, header, 0, "Connection") - - -_protocol_re = re.compile( - r"[-!#$%&\'*+.^_`|~0-9a-zA-Z]+(?:/[-!#$%&\'*+.^_`|~0-9a-zA-Z]+)?" -) - - -def parse_upgrade_protocol( - header: str, pos: int, header_name: str -) -> Tuple[UpgradeProtocol, int]: - """ - Parse an Upgrade protocol from ``header`` at the given position. - - Return the protocol value and the new position. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - match = _protocol_re.match(header, pos) - if match is None: - raise InvalidHeaderFormat(header_name, "expected protocol", header, pos) - return cast(UpgradeProtocol, match.group()), match.end() - - -def parse_upgrade(header: str) -> List[UpgradeProtocol]: - """ - Parse an ``Upgrade`` header. - - Return a list of HTTP protocols. - - :param header: value of the ``Upgrade`` header - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - return parse_list(parse_upgrade_protocol, header, 0, "Upgrade") - - -def parse_extension_item_param( - header: str, pos: int, header_name: str -) -> Tuple[ExtensionParameter, int]: - """ - Parse a single extension parameter from ``header`` at the given position. - - Return a ``(name, value)`` pair and the new position. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - # Extract parameter name. - name, pos = parse_token(header, pos, header_name) - pos = parse_OWS(header, pos) - # Extract parameter value, if there is one. - value: Optional[str] = None - if peek_ahead(header, pos) == "=": - pos = parse_OWS(header, pos + 1) - if peek_ahead(header, pos) == '"': - pos_before = pos # for proper error reporting below - value, pos = parse_quoted_string(header, pos, header_name) - # https://tools.ietf.org/html/rfc6455#section-9.1 says: the value - # after quoted-string unescaping MUST conform to the 'token' ABNF. - if _token_re.fullmatch(value) is None: - raise InvalidHeaderFormat( - header_name, "invalid quoted header content", header, pos_before - ) - else: - value, pos = parse_token(header, pos, header_name) - pos = parse_OWS(header, pos) - - return (name, value), pos - - -def parse_extension_item( - header: str, pos: int, header_name: str -) -> Tuple[ExtensionHeader, int]: - """ - Parse an extension definition from ``header`` at the given position. - - Return an ``(extension name, parameters)`` pair, where ``parameters`` is a - list of ``(name, value)`` pairs, and the new position. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - # Extract extension name. - name, pos = parse_token(header, pos, header_name) - pos = parse_OWS(header, pos) - # Extract all parameters. - parameters = [] - while peek_ahead(header, pos) == ";": - pos = parse_OWS(header, pos + 1) - parameter, pos = parse_extension_item_param(header, pos, header_name) - parameters.append(parameter) - return (cast(ExtensionName, name), parameters), pos - - -def parse_extension(header: str) -> List[ExtensionHeader]: - """ - Parse a ``Sec-WebSocket-Extensions`` header. - - Return a list of WebSocket extensions and their parameters in this format:: - - [ - ( - 'extension name', - [ - ('parameter name', 'parameter value'), - .... - ] - ), - ... - ] - - Parameter values are ``None`` when no value is provided. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - return parse_list(parse_extension_item, header, 0, "Sec-WebSocket-Extensions") - - -parse_extension_list = parse_extension # alias for backwards compatibility - - -def build_extension_item( - name: ExtensionName, parameters: List[ExtensionParameter] -) -> str: - """ - Build an extension definition. - - This is the reverse of :func:`parse_extension_item`. - - """ - return "; ".join( - [cast(str, name)] - + [ - # Quoted strings aren't necessary because values are always tokens. - name if value is None else f"{name}={value}" - for name, value in parameters - ] - ) - - -def build_extension(extensions: Sequence[ExtensionHeader]) -> str: - """ - Build a ``Sec-WebSocket-Extensions`` header. - - This is the reverse of :func:`parse_extension`. - - """ - return ", ".join( - build_extension_item(name, parameters) for name, parameters in extensions - ) - - -build_extension_list = build_extension # alias for backwards compatibility - - -def parse_subprotocol_item( - header: str, pos: int, header_name: str -) -> Tuple[Subprotocol, int]: - """ - Parse a subprotocol from ``header`` at the given position. - - Return the subprotocol value and the new position. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - item, pos = parse_token(header, pos, header_name) - return cast(Subprotocol, item), pos - - -def parse_subprotocol(header: str) -> List[Subprotocol]: - """ - Parse a ``Sec-WebSocket-Protocol`` header. - - Return a list of WebSocket subprotocols. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - return parse_list(parse_subprotocol_item, header, 0, "Sec-WebSocket-Protocol") - - -parse_subprotocol_list = parse_subprotocol # alias for backwards compatibility - - -def build_subprotocol(protocols: Sequence[Subprotocol]) -> str: - """ - Build a ``Sec-WebSocket-Protocol`` header. - - This is the reverse of :func:`parse_subprotocol`. - - """ - return ", ".join(protocols) - - -build_subprotocol_list = build_subprotocol # alias for backwards compatibility - - -def build_www_authenticate_basic(realm: str) -> str: - """ - Build a ``WWW-Authenticate`` header for HTTP Basic Auth. - - :param realm: authentication realm - - """ - # https://tools.ietf.org/html/rfc7617#section-2 - realm = build_quoted_string(realm) - charset = build_quoted_string("UTF-8") - return f"Basic realm={realm}, charset={charset}" - - -_token68_re = re.compile(r"[A-Za-z0-9-._~+/]+=*") - - -def parse_token68(header: str, pos: int, header_name: str) -> Tuple[str, int]: - """ - Parse a token68 from ``header`` at the given position. - - Return the token value and the new position. - - :raises ~websockets.exceptions.InvalidHeaderFormat: on invalid inputs. - - """ - match = _token68_re.match(header, pos) - if match is None: - raise InvalidHeaderFormat(header_name, "expected token68", header, pos) - return match.group(), match.end() - - -def parse_end(header: str, pos: int, header_name: str) -> None: - """ - Check that parsing reached the end of header. - - """ - if pos < len(header): - raise InvalidHeaderFormat(header_name, "trailing data", header, pos) - - -def parse_authorization_basic(header: str) -> Tuple[str, str]: - """ - Parse an ``Authorization`` header for HTTP Basic Auth. - - Return a ``(username, password)`` tuple. - - :param header: value of the ``Authorization`` header - :raises InvalidHeaderFormat: on invalid inputs - :raises InvalidHeaderValue: on unsupported inputs - - """ - # https://tools.ietf.org/html/rfc7235#section-2.1 - # https://tools.ietf.org/html/rfc7617#section-2 - scheme, pos = parse_token(header, 0, "Authorization") - if scheme.lower() != "basic": - raise InvalidHeaderValue("Authorization", f"unsupported scheme: {scheme}") - if peek_ahead(header, pos) != " ": - raise InvalidHeaderFormat( - "Authorization", "expected space after scheme", header, pos - ) - pos += 1 - basic_credentials, pos = parse_token68(header, pos, "Authorization") - parse_end(header, pos, "Authorization") - - try: - user_pass = base64.b64decode(basic_credentials.encode()).decode() - except binascii.Error: - raise InvalidHeaderValue( - "Authorization", "expected base64-encoded credentials" - ) from None - try: - username, password = user_pass.split(":", 1) - except ValueError: - raise InvalidHeaderValue( - "Authorization", "expected username:password credentials" - ) from None - - return username, password - - -def build_authorization_basic(username: str, password: str) -> str: - """ - Build an ``Authorization`` header for HTTP Basic Auth. - - This is the reverse of :func:`parse_authorization_basic`. - - """ - # https://tools.ietf.org/html/rfc7617#section-2 - assert ":" not in username - user_pass = f"{username}:{password}" - basic_credentials = base64.b64encode(user_pass.encode()).decode() - return "Basic " + basic_credentials diff --git a/venv/Lib/site-packages/websockets/http.py b/venv/Lib/site-packages/websockets/http.py index ba6d274b..464e942a 100644 --- a/venv/Lib/site-packages/websockets/http.py +++ b/venv/Lib/site-packages/websockets/http.py @@ -1,57 +1,36 @@ """ -:mod:`websockets.http` module provides basic HTTP/1.1 support. It is merely -:adequate for WebSocket handshake messages. +The :mod:`websockets.http` module provides HTTP parsing functions. They're +merely adequate for the WebSocket handshake messages. -These APIs cannot be imported from :mod:`websockets`. They must be imported -from :mod:`websockets.http`. +These functions cannot be imported from :mod:`websockets`; they must be +imported from :mod:`websockets.http`. """ import asyncio +import http.client import re import sys -from typing import ( - Any, - Dict, - Iterable, - Iterator, - List, - Mapping, - MutableMapping, - Tuple, - Union, -) from .version import version as websockets_version -__all__ = [ - "read_request", - "read_response", - "Headers", - "MultipleValuesError", - "USER_AGENT", -] +__all__ = ['read_request', 'read_response', 'USER_AGENT'] MAX_HEADERS = 256 MAX_LINE = 4096 -USER_AGENT = f"Python/{sys.version[:3]} websockets/{websockets_version}" - - -def d(value: bytes) -> str: - """ - Decode a bytestring for interpolating into an error message. - - """ - return value.decode(errors="backslashreplace") +USER_AGENT = ' '.join(( + 'Python/{}'.format(sys.version[:3]), + 'websockets/{}'.format(websockets_version), +)) # See https://tools.ietf.org/html/rfc7230#appendix-B. # Regex for validating header names. -_token_re = re.compile(rb"[-!#$%&\'*+.^_`|~0-9a-zA-Z]+") +_token_re = re.compile(rb'^[-!#$%&\'*+.^_`|~0-9a-zA-Z]+$') # Regex for validating header values. @@ -64,26 +43,28 @@ _token_re = re.compile(rb"[-!#$%&\'*+.^_`|~0-9a-zA-Z]+") # See also https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4189 -_value_re = re.compile(rb"[\x09\x20-\x7e\x80-\xff]*") +_value_re = re.compile(rb'^[\x09\x20-\x7e\x80-\xff]*$') -async def read_request(stream: asyncio.StreamReader) -> Tuple[str, "Headers"]: +@asyncio.coroutine +def read_request(stream): """ - Read an HTTP/1.1 GET request and return ``(path, headers)``. + Read an HTTP/1.1 GET request from ``stream``. + + ``stream`` is an :class:`~asyncio.StreamReader`. + + Return ``(path, headers)`` where ``path`` is a :class:`str` and + ``headers`` is a list of ``(name, value)`` tuples. ``path`` isn't URL-decoded or validated in any way. - ``path`` and ``headers`` are expected to contain only ASCII characters. - Other characters are represented with surrogate escapes. + Non-ASCII characters are represented with surrogate escapes. - :func:`read_request` doesn't attempt to read the request body because - WebSocket handshake requests don't have one. If the request contains a - body, it may be read from ``stream`` after this coroutine returns. + Raise an exception if the request isn't well formatted. - :param stream: input to read the request from - :raises EOFError: if the connection is closed without a full HTTP request - :raises SecurityError: if the request exceeds a security limit - :raises ValueError: if the request isn't well formatted + Don't attempt to read the request body because WebSocket handshake + requests don't have one. If the request contains a body, it may be + read from ``stream`` after this coroutine returns. """ # https://tools.ietf.org/html/rfc7230#section-3.1.1 @@ -92,42 +73,41 @@ async def read_request(stream: asyncio.StreamReader) -> Tuple[str, "Headers"]: # version and because path isn't checked. Since WebSocket software tends # to implement HTTP/1.1 strictly, there's little need for lenient parsing. - try: - request_line = await read_line(stream) - except EOFError as exc: - raise EOFError("connection closed while reading HTTP request line") from exc + # Given the implementation of read_line(), request_line ends with CRLF. + request_line = yield from read_line(stream) - try: - method, raw_path, version = request_line.split(b" ", 2) - except ValueError: # not enough values to unpack (expected 3, got 1-2) - raise ValueError(f"invalid HTTP request line: {d(request_line)}") from None + # This may raise "ValueError: not enough values to unpack" + method, path, version = request_line[:-2].split(b' ', 2) - if method != b"GET": - raise ValueError(f"unsupported HTTP method: {d(method)}") - if version != b"HTTP/1.1": - raise ValueError(f"unsupported HTTP version: {d(version)}") - path = raw_path.decode("ascii", "surrogateescape") + if method != b'GET': + raise ValueError("Unsupported HTTP method: %r" % method) + if version != b'HTTP/1.1': + raise ValueError("Unsupported HTTP version: %r" % version) - headers = await read_headers(stream) + path = path.decode('ascii', 'surrogateescape') + + headers = yield from read_headers(stream) return path, headers -async def read_response(stream: asyncio.StreamReader) -> Tuple[int, str, "Headers"]: +@asyncio.coroutine +def read_response(stream): """ - Read an HTTP/1.1 response and return ``(status_code, reason, headers)``. + Read an HTTP/1.1 response from ``stream``. + + ``stream`` is an :class:`~asyncio.StreamReader`. - ``reason`` and ``headers`` are expected to contain only ASCII characters. - Other characters are represented with surrogate escapes. + Return ``(status_code, headers)`` where ``status_code`` is a :class:`int` + and ``headers`` is a list of ``(name, value)`` tuples. + + Non-ASCII characters are represented with surrogate escapes. - :func:`read_request` doesn't attempt to read the response body because - WebSocket handshake responses don't have one. If the response contains a - body, it may be read from ``stream`` after this coroutine returns. + Raise an exception if the response isn't well formatted. - :param stream: input to read the response from - :raises EOFError: if the connection is closed without a full HTTP response - :raises SecurityError: if the response exceeds a security limit - :raises ValueError: if the response isn't well formatted + Don't attempt to read the response body, because WebSocket handshake + responses don't have one. If the response contains a body, it may be + read from ``stream`` after this coroutine returns. """ # https://tools.ietf.org/html/rfc7230#section-3.1.2 @@ -135,37 +115,36 @@ async def read_response(stream: asyncio.StreamReader) -> Tuple[int, str, "Header # As in read_request, parsing is simple because a fixed value is expected # for version, status_code is a 3-digit number, and reason can be ignored. - try: - status_line = await read_line(stream) - except EOFError as exc: - raise EOFError("connection closed while reading HTTP status line") from exc - - try: - version, raw_status_code, raw_reason = status_line.split(b" ", 2) - except ValueError: # not enough values to unpack (expected 3, got 1-2) - raise ValueError(f"invalid HTTP status line: {d(status_line)}") from None - - if version != b"HTTP/1.1": - raise ValueError(f"unsupported HTTP version: {d(version)}") - try: - status_code = int(raw_status_code) - except ValueError: # invalid literal for int() with base 10 - raise ValueError(f"invalid HTTP status code: {d(raw_status_code)}") from None + # Given the implementation of read_line(), status_line ends with CRLF. + status_line = yield from read_line(stream) + + # This may raise "ValueError: not enough values to unpack" + version, status_code, reason = status_line[:-2].split(b' ', 2) + + if version != b'HTTP/1.1': + raise ValueError("Unsupported HTTP version: %r" % version) + # This may raise "ValueError: invalid literal for int() with base 10" + status_code = int(status_code) if not 100 <= status_code < 1000: - raise ValueError(f"unsupported HTTP status code: {d(raw_status_code)}") - if not _value_re.fullmatch(raw_reason): - raise ValueError(f"invalid HTTP reason phrase: {d(raw_reason)}") - reason = raw_reason.decode() + raise ValueError("Unsupported HTTP status_code code: %d" % status_code) + if not _value_re.match(reason): + raise ValueError("Invalid HTTP reason phrase: %r" % reason) - headers = await read_headers(stream) + headers = yield from read_headers(stream) - return status_code, reason, headers + return status_code, headers -async def read_headers(stream: asyncio.StreamReader) -> "Headers": +@asyncio.coroutine +def read_headers(stream): """ Read HTTP headers from ``stream``. + ``stream`` is an :class:`~asyncio.StreamReader`. + + Return ``(start_line, headers)`` where ``start_line`` is :class:`bytes` + and ``headers`` is a list of ``(name, value)`` tuples. + Non-ASCII characters are represented with surrogate escapes. """ @@ -173,188 +152,57 @@ async def read_headers(stream: asyncio.StreamReader) -> "Headers": # We don't attempt to support obsolete line folding. - headers = Headers() - for _ in range(MAX_HEADERS + 1): - try: - line = await read_line(stream) - except EOFError as exc: - raise EOFError("connection closed while reading HTTP headers") from exc - if line == b"": + headers = [] + for _ in range(MAX_HEADERS): + line = yield from read_line(stream) + if line == b'\r\n': break - try: - raw_name, raw_value = line.split(b":", 1) - except ValueError: # not enough values to unpack (expected 2, got 1) - raise ValueError(f"invalid HTTP header line: {d(line)}") from None - if not _token_re.fullmatch(raw_name): - raise ValueError(f"invalid HTTP header name: {d(raw_name)}") - raw_value = raw_value.strip(b" \t") - if not _value_re.fullmatch(raw_value): - raise ValueError(f"invalid HTTP header value: {d(raw_value)}") + # This may raise "ValueError: not enough values to unpack" + name, value = line[:-2].split(b':', 1) + if not _token_re.match(name): + raise ValueError("Invalid HTTP header name: %r" % name) + value = value.strip(b' \t') + if not _value_re.match(value): + raise ValueError("Invalid HTTP header value: %r" % value) - name = raw_name.decode("ascii") # guaranteed to be ASCII at this point - value = raw_value.decode("ascii", "surrogateescape") - headers[name] = value + headers.append(( + name.decode('ascii'), # guaranteed to be ASCII at this point + value.decode('ascii', 'surrogateescape'), + )) else: - raise websockets.exceptions.SecurityError("too many HTTP headers") + raise ValueError("Too many HTTP headers") return headers -async def read_line(stream: asyncio.StreamReader) -> bytes: +@asyncio.coroutine +def read_line(stream): """ Read a single line from ``stream``. - CRLF is stripped from the return value. + ``stream`` is an :class:`~asyncio.StreamReader`. """ - # Security: this is bounded by the StreamReader's limit (default = 32 KiB). - line = await stream.readline() - # Security: this guarantees header values are small (hard-coded = 4 KiB) + # Security: this is bounded by the StreamReader's limit (default = 32kB). + line = yield from stream.readline() + # Security: this guarantees header values are small (hardcoded = 4kB) if len(line) > MAX_LINE: - raise websockets.exceptions.SecurityError("line too long") + raise ValueError("Line too long") # Not mandatory but safe - https://tools.ietf.org/html/rfc7230#section-3.5 - if not line.endswith(b"\r\n"): - raise EOFError("line without CRLF") - return line[:-2] - + if not line.endswith(b'\r\n'): + raise ValueError("Line without CRLF") + return line -class MultipleValuesError(LookupError): - """ - Exception raised when :class:`Headers` has more than one value for a key. +def build_headers(raw_headers): """ + Build a date structure for HTTP headers from a list of name - value pairs. - def __str__(self) -> str: - # Implement the same logic as KeyError_str in Objects/exceptions.c. - if len(self.args) == 1: - return repr(self.args[0]) - return super().__str__() - + See also https://github.com/aaugustin/websockets/issues/210. -class Headers(MutableMapping[str, str]): """ - Efficient data structure for manipulating HTTP headers. - - A :class:`list` of ``(name, values)`` is inefficient for lookups. - - A :class:`dict` doesn't suffice because header names are case-insensitive - and multiple occurrences of headers with the same name are possible. - - :class:`Headers` stores HTTP headers in a hybrid data structure to provide - efficient insertions and lookups while preserving the original data. - - In order to account for multiple values with minimal hassle, - :class:`Headers` follows this logic: - - - When getting a header with ``headers[name]``: - - if there's no value, :exc:`KeyError` is raised; - - if there's exactly one value, it's returned; - - if there's more than one value, :exc:`MultipleValuesError` is raised. - - - When setting a header with ``headers[name] = value``, the value is - appended to the list of values for that header. - - - When deleting a header with ``del headers[name]``, all values for that - header are removed (this is slow). - - Other methods for manipulating headers are consistent with this logic. - - As long as no header occurs multiple times, :class:`Headers` behaves like - :class:`dict`, except keys are lower-cased to provide case-insensitivity. - - Two methods support support manipulating multiple values explicitly: - - - :meth:`get_all` returns a list of all values for a header; - - :meth:`raw_items` returns an iterator of ``(name, values)`` pairs. - - """ - - __slots__ = ["_dict", "_list"] - - def __init__(self, *args: Any, **kwargs: str) -> None: - self._dict: Dict[str, List[str]] = {} - self._list: List[Tuple[str, str]] = [] - # MutableMapping.update calls __setitem__ for each (name, value) pair. - self.update(*args, **kwargs) - - def __str__(self) -> str: - return "".join(f"{key}: {value}\r\n" for key, value in self._list) + "\r\n" - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self._list!r})" - - def copy(self) -> "Headers": - copy = self.__class__() - copy._dict = self._dict.copy() - copy._list = self._list.copy() - return copy - - # Collection methods - - def __contains__(self, key: object) -> bool: - return isinstance(key, str) and key.lower() in self._dict - - def __iter__(self) -> Iterator[str]: - return iter(self._dict) - - def __len__(self) -> int: - return len(self._dict) - - # MutableMapping methods - - def __getitem__(self, key: str) -> str: - value = self._dict[key.lower()] - if len(value) == 1: - return value[0] - else: - raise MultipleValuesError(key) - - def __setitem__(self, key: str, value: str) -> None: - self._dict.setdefault(key.lower(), []).append(value) - self._list.append((key, value)) - - def __delitem__(self, key: str) -> None: - key_lower = key.lower() - self._dict.__delitem__(key_lower) - # This is inefficent. Fortunately deleting HTTP headers is uncommon. - self._list = [(k, v) for k, v in self._list if k.lower() != key_lower] - - def __eq__(self, other: Any) -> bool: - if not isinstance(other, Headers): - return NotImplemented - return self._list == other._list - - def clear(self) -> None: - """ - Remove all headers. - - """ - self._dict = {} - self._list = [] - - # Methods for handling multiple values - - def get_all(self, key: str) -> List[str]: - """ - Return the (possibly empty) list of all values for a header. - - :param key: header name - - """ - return self._dict.get(key.lower(), []) - - def raw_items(self) -> Iterator[Tuple[str, str]]: - """ - Return an iterator of all values as ``(name, value)`` pairs. - - """ - return iter(self._list) - - -HeadersLike = Union[Headers, Mapping[str, str], Iterable[Tuple[str, str]]] - - -# at the bottom to allow circular import, because AbortHandshake depends on HeadersLike -import websockets.exceptions # isort:skip # noqa + headers = http.client.HTTPMessage() + headers._headers = raw_headers # HACK + return headers diff --git a/venv/Lib/site-packages/websockets/protocol.py b/venv/Lib/site-packages/websockets/protocol.py index 6c29b2a5..bfe7e231 100644 --- a/venv/Lib/site-packages/websockets/protocol.py +++ b/venv/Lib/site-packages/websockets/protocol.py @@ -1,361 +1,189 @@ """ -:mod:`websockets.protocol` handles WebSocket control and data frames. - -See `sections 4 to 8 of RFC 6455`_. +The :mod:`websockets.protocol` module handles WebSocket control and data +frames as specified in `sections 4 to 8 of RFC 6455`_. .. _sections 4 to 8 of RFC 6455: http://tools.ietf.org/html/rfc6455#section-4 """ import asyncio +import asyncio.queues import codecs import collections -import enum import logging import random import struct -import sys -import warnings -from typing import ( - Any, - AsyncIterable, - AsyncIterator, - Awaitable, - Deque, - Dict, - Iterable, - List, - Optional, - Union, - cast, -) +from .compatibility import asyncio_ensure_future from .exceptions import ( - ConnectionClosed, - ConnectionClosedError, - ConnectionClosedOK, - InvalidState, - PayloadTooBig, - ProtocolError, + ConnectionClosed, InvalidState, PayloadTooBig, WebSocketProtocolError ) -from .extensions.base import Extension from .framing import * from .handshake import * -from .http import Headers -from .typing import Data -__all__ = ["WebSocketCommonProtocol"] +__all__ = ['WebSocketCommonProtocol'] logger = logging.getLogger(__name__) # A WebSocket connection goes through the following four states, in order: - -class State(enum.IntEnum): - CONNECTING, OPEN, CLOSING, CLOSED = range(4) - +CONNECTING, OPEN, CLOSING, CLOSED = range(4) # In order to ensure consistency, the code always checks the current value of # WebSocketCommonProtocol.state before assigning a new value and never yields # between the check and the assignment. -class WebSocketCommonProtocol(asyncio.Protocol): +class WebSocketCommonProtocol(asyncio.StreamReaderProtocol): """ - :class:`~asyncio.Protocol` subclass implementing the data transfer phase. - - Once the WebSocket connection is established, during the data transfer - phase, the protocol is almost symmetrical between the server side and the - client side. :class:`WebSocketCommonProtocol` implements logic that's - shared between servers and clients.. - - Subclasses such as :class:`~websockets.server.WebSocketServerProtocol` and - :class:`~websockets.client.WebSocketClientProtocol` implement the opening - handshake, which is different between servers and clients. - - :class:`WebSocketCommonProtocol` performs four functions: - - * It runs a task that stores incoming data frames in a queue and makes - them available with the :meth:`recv` coroutine. - * It sends outgoing data frames with the :meth:`send` coroutine. - * It deals with control frames automatically. - * It performs the closing handshake. + This class implements common parts of the WebSocket protocol. - :class:`WebSocketCommonProtocol` supports asynchronous iteration:: + It assumes that the WebSocket connection is established. The handshake is + managed in subclasses such as + :class:`~websockets.server.WebSocketServerProtocol` and + :class:`~websockets.client.WebSocketClientProtocol`. - async for message in websocket: - await process(message) + It runs a task that stores incoming data frames in a queue and deals with + control frames automatically. It sends outgoing data frames and performs + the closing handshake. - The iterator yields incoming messages. It exits normally when the - connection is closed with the close code 1000 (OK) or 1001 (going away). - It raises a :exc:`~websockets.exceptions.ConnectionClosedError` exception - when the connection is closed with any other code. + The ``host``, ``port`` and ``secure`` parameters are simply stored as + attributes for handlers that need them. - Once the connection is open, a `Ping frame`_ is sent every - ``ping_interval`` seconds. This serves as a keepalive. It helps keeping - the connection open, especially in the presence of proxies with short - timeouts on inactive connections. Set ``ping_interval`` to ``None`` to - disable this behavior. - - .. _Ping frame: https://tools.ietf.org/html/rfc6455#section-5.5.2 - - If the corresponding `Pong frame`_ isn't received within ``ping_timeout`` - seconds, the connection is considered unusable and is closed with - code 1011. This ensures that the remote endpoint remains responsive. Set - ``ping_timeout`` to ``None`` to disable this behavior. - - .. _Pong frame: https://tools.ietf.org/html/rfc6455#section-5.5.3 - - The ``close_timeout`` parameter defines a maximum wait time in seconds for - completing the closing handshake and terminating the TCP connection. - :meth:`close` completes in at most ``4 * close_timeout`` on the server - side and ``5 * close_timeout`` on the client side. - - ``close_timeout`` needs to be a parameter of the protocol because - ``websockets`` usually calls :meth:`close` implicitly: - - - on the server side, when the connection handler terminates, - - on the client side, when exiting the context manager for the connection. - - To apply a timeout to any other API, wrap it in :func:`~asyncio.wait_for`. + The ``timeout`` parameter defines the maximum wait time in seconds for + completing the closing handshake and, only on the client side, for + terminating the TCP connection. :meth:`close()` will complete in at most + this time on the server side and twice this time on the client side. The ``max_size`` parameter enforces the maximum size for incoming messages - in bytes. The default value is 1 MiB. ``None`` disables the limit. If a - message larger than the maximum size is received, :meth:`recv` will - raise :exc:`~websockets.exceptions.ConnectionClosedError` and the - connection will be closed with code 1009. - - The ``max_queue`` parameter sets the maximum length of the queue that - holds incoming messages. The default value is ``32``. ``None`` disables - the limit. Messages are added to an in-memory queue when they're received; - then :meth:`recv` pops from that queue. In order to prevent excessive - memory consumption when messages are received faster than they can be - processed, the queue must be bounded. If the queue fills up, the protocol - stops processing incoming data until :meth:`recv` is called. In this - situation, various receive buffers (at least in ``asyncio`` and in the OS) - will fill up, then the TCP receive window will shrink, slowing down - transmission to avoid packet loss. + in bytes. The default value is 1MB. ``None`` disables the limit. If a + message larger than the maximum size is received, :meth:`recv()` will + raise :exc:`~websockets.exceptions.ConnectionClosed` and the connection + will be closed with status code 1009. + + The ``max_queue`` parameter sets the maximum length of the queue that holds + incoming messages. The default value is 32. 0 disables the limit. Messages + are added to an in-memory queue when they're received; then :meth:`recv()` + pops from that queue. In order to prevent excessive memory consumption when + messages are received faster than they can be processed, the queue must be + bounded. If the queue fills up, the protocol stops processing incoming data + until :meth:`recv()` is called. In this situation, various receive buffers + (at least in ``asyncio`` and in the OS) will fill up, then the TCP receive + window will shrink, slowing down transmission to avoid packet loss. Since Python can use up to 4 bytes of memory to represent a single - character, each connection may use up to ``4 * max_size * max_queue`` - bytes of memory to store incoming messages. By default, this is 128 MiB. - You may want to lower the limits, depending on your application's - requirements. + character, each websocket connection may use up to ``4 * max_size * + max_queue`` bytes of memory to store incoming messages. By default, + this is 128MB. You may want to lower the limits, depending on your + application's requirements. The ``read_limit`` argument sets the high-water limit of the buffer for incoming bytes. The low-water limit is half the high-water limit. The - default value is 64 KiB, half of asyncio's default (based on the current + default value is 64kB, half of asyncio's default (based on the current implementation of :class:`~asyncio.StreamReader`). The ``write_limit`` argument sets the high-water limit of the buffer for outgoing bytes. The low-water limit is a quarter of the high-water limit. - The default value is 64 KiB, equal to asyncio's default (based on the - current implementation of ``FlowControlMixin``). + The default value is 64kB, equal to asyncio's default (based on the + current implementation of ``_FlowControlMixin``). As soon as the HTTP request and response in the opening handshake are - processed: + processed, the request path is available in the :attr:`path` attribute, + and the request and response HTTP headers are available: + + * as a :class:`~http.client.HTTPMessage` in the :attr:`request_headers` + and :attr:`response_headers` attributes + * as an iterable of (name, value) pairs in the :attr:`raw_request_headers` + and :attr:`raw_response_headers` attributes - * the request path is available in the :attr:`path` attribute; - * the request and response HTTP headers are available in the - :attr:`request_headers` and :attr:`response_headers` attributes, - which are :class:`~websockets.http.Headers` instances. + These attributes must be treated as immutable. If a subprotocol was negotiated, it's available in the :attr:`subprotocol` attribute. - Once the connection is closed, the code is available in the + Once the connection is closed, the status code is available in the :attr:`close_code` attribute and the reason in :attr:`close_reason`. - All these attributes must be treated as read-only. - """ - - # There are only two differences between the client-side and server-side - # behavior: masking the payload and closing the underlying TCP connection. - # Set is_client = True/False and side = "client"/"server" to pick a side. - is_client: bool - side: str = "undefined" - - def __init__( - self, - *, - ping_interval: Optional[float] = 20, - ping_timeout: Optional[float] = 20, - close_timeout: Optional[float] = None, - max_size: Optional[int] = 2 ** 20, - max_queue: Optional[int] = 2 ** 5, - read_limit: int = 2 ** 16, - write_limit: int = 2 ** 16, - loop: Optional[asyncio.AbstractEventLoop] = None, - # The following arguments are kept only for backwards compatibility. - host: Optional[str] = None, - port: Optional[int] = None, - secure: Optional[bool] = None, - legacy_recv: bool = False, - timeout: Optional[float] = None, - ) -> None: - # Backwards compatibility: close_timeout used to be called timeout. - if timeout is None: - timeout = 10 - else: - warnings.warn("rename timeout to close_timeout", DeprecationWarning) - # If both are specified, timeout is ignored. - if close_timeout is None: - close_timeout = timeout - - self.ping_interval = ping_interval - self.ping_timeout = ping_timeout - self.close_timeout = close_timeout + # There are only two differences between the client-side and the server- + # side behavior: masking the payload and closing the underlying TCP + # connection. This class implements the server-side behavior by default. + # To get the client-side behavior, set is_client = True. + + is_client = False + state = OPEN + + def __init__(self, *, + host=None, port=None, secure=None, + timeout=10, max_size=2 ** 20, max_queue=2 ** 5, + read_limit=2 ** 16, write_limit=2 ** 16, + loop=None, legacy_recv=False): + self.host = host + self.port = port + self.secure = secure + self.timeout = timeout self.max_size = max_size self.max_queue = max_queue self.read_limit = read_limit self.write_limit = write_limit + # Store a reference to loop to avoid relying on self._loop, a private + # attribute of StreamReaderProtocol, inherited from _FlowControlMixin. if loop is None: loop = asyncio.get_event_loop() self.loop = loop - self._host = host - self._port = port - self._secure = secure self.legacy_recv = legacy_recv - # Configure read buffer limits. The high-water limit is defined by - # ``self.read_limit``. The ``limit`` argument controls the line length - # limit and half the buffer limit of :class:`~asyncio.StreamReader`. - # That's why it must be set to half of ``self.read_limit``. - self.reader = asyncio.StreamReader(limit=read_limit // 2, loop=loop) - - # Copied from asyncio.FlowControlMixin - self._paused = False - self._drain_waiter: Optional[asyncio.Future[None]] = None - - self._drain_lock = asyncio.Lock( - loop=loop if sys.version_info[:2] < (3, 8) else None - ) - - # This class implements the data transfer and closing handshake, which - # are shared between the client-side and the server-side. - # Subclasses implement the opening handshake and, on success, execute - # :meth:`connection_open` to change the state to OPEN. - self.state = State.CONNECTING - logger.debug("%s - state = CONNECTING", self.side) - - # HTTP protocol parameters. - self.path: str - self.request_headers: Headers - self.response_headers: Headers - - # WebSocket protocol parameters. - self.extensions: List[Extension] = [] - self.subprotocol: Optional[str] = None - - # The close code and reason are set when receiving a close frame or - # losing the TCP connection. - self.close_code: int - self.close_reason: str - - # Completed when the connection state becomes CLOSED. Translates the - # :meth:`connection_lost` callback to a :class:`~asyncio.Future` - # that can be awaited. (Other :class:`~asyncio.Protocol` callbacks are - # translated by ``self.stream_reader``). - self.connection_lost_waiter: asyncio.Future[None] = loop.create_future() - - # Queue of received messages. - self.messages: Deque[Data] = collections.deque() - self._pop_message_waiter: Optional[asyncio.Future[None]] = None - self._put_message_waiter: Optional[asyncio.Future[None]] = None - - # Protect sending fragmented messages. - self._fragmented_message_waiter: Optional[asyncio.Future[None]] = None + # This limit is both the line length limit and half the buffer limit. + stream_reader = asyncio.StreamReader(limit=read_limit // 2, loop=loop) + super().__init__(stream_reader, self.client_connected, loop) - # Mapping of ping IDs to waiters, in chronological order. - self.pings: Dict[bytes, asyncio.Future[None]] = {} + self.reader = None + self.writer = None + self._drain_lock = asyncio.Lock(loop=loop) - # Task running the data transfer. - self.transfer_data_task: asyncio.Task[None] + self.path = None + self.request_headers = None + self.raw_request_headers = None + self.response_headers = None + self.raw_response_headers = None - # Exception that occurred during data transfer, if any. - self.transfer_data_exc: Optional[BaseException] = None + self.subprotocol = None - # Task sending keepalive pings. - self.keepalive_ping_task: asyncio.Task[None] + # Code and reason must be set when the closing handshake completes. + self.close_code = None + self.close_reason = '' - # Task closing the TCP connection. - self.close_connection_task: asyncio.Task[None] + # Futures tracking steps in the connection's lifecycle. + # Set to True when the opening handshake has completed properly. + self.opening_handshake = asyncio.Future(loop=loop) + # Set to True when the closing handshake has completed properly and to + # False when the connection terminates abnormally. + self.closing_handshake = asyncio.Future(loop=loop) + # Set to None when the connection state becomes CLOSED. + self.connection_closed = asyncio.Future(loop=loop) - # Copied from asyncio.FlowControlMixin - async def _drain_helper(self) -> None: # pragma: no cover - if self.connection_lost_waiter.done(): - raise ConnectionResetError("Connection lost") - if not self._paused: - return - waiter = self._drain_waiter - assert waiter is None or waiter.cancelled() - waiter = self.loop.create_future() - self._drain_waiter = waiter - await waiter - - # Copied from asyncio.StreamWriter - async def _drain(self) -> None: # pragma: no cover - if self.reader is not None: - exc = self.reader.exception() - if exc is not None: - raise exc - if self.transport is not None: - if self.transport.is_closing(): - # Yield to the event loop so connection_lost() may be - # called. Without this, _drain_helper() would return - # immediately, and code that calls - # write(...); yield from drain() - # in a loop would never call connection_lost(), so it - # would not see an error when the socket is closed. - await asyncio.sleep( - 0, loop=self.loop if sys.version_info[:2] < (3, 8) else None - ) - await self._drain_helper() - - def connection_open(self) -> None: - """ - Callback when the WebSocket opening handshake completes. - - Enter the OPEN state and start the data transfer phase. + # Queue of received messages. + self.messages = asyncio.queues.Queue(max_queue, loop=loop) - """ - # 4.1. The WebSocket Connection is Established. - assert self.state is State.CONNECTING - self.state = State.OPEN - logger.debug("%s - state = OPEN", self.side) - # Start the task that receives incoming WebSocket messages. - self.transfer_data_task = self.loop.create_task(self.transfer_data()) - # Start the task that sends pings at regular intervals. - self.keepalive_ping_task = self.loop.create_task(self.keepalive_ping()) - # Start the task that eventually closes the TCP connection. - self.close_connection_task = self.loop.create_task(self.close_connection()) + # Mapping of ping IDs to waiters, in chronological order. + self.pings = collections.OrderedDict() - @property - def host(self) -> Optional[str]: - alternative = "remote_address" if self.is_client else "local_address" - warnings.warn(f"use {alternative}[0] instead of host", DeprecationWarning) - return self._host + # Task managing the connection, initalized in self.client_connected. + self.worker_task = None - @property - def port(self) -> Optional[int]: - alternative = "remote_address" if self.is_client else "local_address" - warnings.warn(f"use {alternative}[1] instead of port", DeprecationWarning) - return self._port - - @property - def secure(self) -> Optional[bool]: - warnings.warn(f"don't use secure", DeprecationWarning) - return self._secure + # In a subclass implementing the opening handshake, the state will be + # CONNECTING at this point. + if self.state == OPEN: + self.opening_handshake.set_result(True) # Public API @property - def local_address(self) -> Any: + def local_address(self): """ Local address of the connection. @@ -363,15 +191,12 @@ class WebSocketCommonProtocol(asyncio.Protocol): been established yet. """ - try: - transport = self.transport - except AttributeError: + if self.writer is None: return None - else: - return transport.get_extra_info("sockname") + return self.writer.get_extra_info('sockname') @property - def remote_address(self) -> Any: + def remote_address(self): """ Remote address of the connection. @@ -379,1051 +204,486 @@ class WebSocketCommonProtocol(asyncio.Protocol): been established yet. """ - try: - transport = self.transport - except AttributeError: + if self.writer is None: return None - else: - return transport.get_extra_info("peername") + return self.writer.get_extra_info('peername') @property - def open(self) -> bool: + def open(self): """ - ``True`` when the connection is usable. + This property is ``True`` when the connection is usable. - It may be used to detect disconnections. However, this approach is - discouraged per the EAFP_ principle. - - When ``open`` is ``False``, using the connection raises a - :exc:`~websockets.exceptions.ConnectionClosed` exception. + It may be used to detect disconnections but this is discouraged per + the EAFP_ principle. When ``open`` is ``False``, using the connection + raises a :exc:`~websockets.exceptions.ConnectionClosed` exception. .. _EAFP: https://docs.python.org/3/glossary.html#term-eafp """ - return self.state is State.OPEN and not self.transfer_data_task.done() + return self.state == OPEN @property - def closed(self) -> bool: + def state_name(self): """ - ``True`` once the connection is closed. + Current connection state, as a string. - Be aware that both :attr:`open` and :attr:`closed` are ``False`` during - the opening and closing sequences. + Possible states are defined in the WebSocket specification: + CONNECTING, OPEN, CLOSING, or CLOSED. - """ - return self.state is State.CLOSED + To check if the connection is open, use :attr:`open` instead. - async def wait_closed(self) -> None: """ - Wait until the connection is closed. - - This is identical to :attr:`closed`, except it can be awaited. - - This can make it easier to handle connection termination, regardless - of its cause, in tasks that interact with the WebSocket connection. + return ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'][self.state] + @asyncio.coroutine + def close(self, code=1000, reason=''): """ - await asyncio.shield(self.connection_lost_waiter) + This coroutine performs the closing handshake. - async def __aiter__(self) -> AsyncIterator[Data]: - """ - Iterate on received messages. + It waits for the other end to complete the handshake. It doesn't do + anything once the connection is closed. Thus it's idemptotent. - Exit normally when the connection is closed with code 1000 or 1001. + It's safe to wrap this coroutine in :func:`~asyncio.ensure_future` + since errors during connection termination aren't particularly useful. - Raise an exception in other cases. + ``code`` must be an :class:`int` and ``reason`` a :class:`str`. """ + if self.state == OPEN: + # 7.1.2. Start the WebSocket Closing Handshake + # 7.1.3. The WebSocket Closing Handshake is Started + frame_data = serialize_close(code, reason) + yield from self.write_frame(OP_CLOSE, frame_data) + + # If the connection doesn't terminate within the timeout, break out of + # the worker loop. try: - while True: - yield await self.recv() - except ConnectionClosedOK: - return + yield from asyncio.wait_for( + self.worker_task, self.timeout, loop=self.loop) + except asyncio.TimeoutError: + self.worker_task.cancel() - async def recv(self) -> Data: + # The worker should terminate quickly once it has been cancelled. + yield from self.worker_task + + @asyncio.coroutine + def recv(self): """ - Receive the next message. + This coroutine receives the next message. - Return a :class:`str` for a text frame and :class:`bytes` for a binary - frame. + It returns a :class:`str` for a text frame and :class:`bytes` for a + binary frame. When the end of the message stream is reached, :meth:`recv` raises - :exc:`~websockets.exceptions.ConnectionClosed`. Specifically, it - raises :exc:`~websockets.exceptions.ConnectionClosedOK` after a normal - connection closure and - :exc:`~websockets.exceptions.ConnectionClosedError` after a protocol - error or a network failure. + :exc:`~websockets.exceptions.ConnectionClosed`. This can happen after + a normal connection closure, a protocol error or a network failure. .. versionchanged:: 3.0 :meth:`recv` used to return ``None`` instead. Refer to the changelog for details. - Canceling :meth:`recv` is safe. There's no risk of losing the next - message. The next invocation of :meth:`recv` will return it. This - makes it possible to enforce a timeout by wrapping :meth:`recv` in - :func:`~asyncio.wait_for`. - - :raises ~websockets.exceptions.ConnectionClosed: when the - connection is closed - :raises RuntimeError: if two coroutines call :meth:`recv` concurrently - - """ - if self._pop_message_waiter is not None: - raise RuntimeError( - "cannot call recv while another coroutine " - "is already waiting for the next message" - ) - - # Don't await self.ensure_open() here: - # - messages could be available in the queue even if the connection - # is closed; - # - messages could be received before the closing frame even if the - # connection is closing. - - # Wait until there's a message in the queue (if necessary) or the - # connection is closed. - while len(self.messages) <= 0: - pop_message_waiter: asyncio.Future[None] = self.loop.create_future() - self._pop_message_waiter = pop_message_waiter - try: - # If asyncio.wait() is canceled, it doesn't cancel - # pop_message_waiter and self.transfer_data_task. - await asyncio.wait( - [pop_message_waiter, self.transfer_data_task], - loop=self.loop if sys.version_info[:2] < (3, 8) else None, - return_when=asyncio.FIRST_COMPLETED, - ) - finally: - self._pop_message_waiter = None - - # If asyncio.wait(...) exited because self.transfer_data_task - # completed before receiving a new message, raise a suitable - # exception (or return None if legacy_recv is enabled). - if not pop_message_waiter.done(): - if self.legacy_recv: - return None # type: ignore - else: - # Wait until the connection is closed to raise - # ConnectionClosed with the correct code and reason. - await self.ensure_open() - - # Pop a message from the queue. - message = self.messages.popleft() - - # Notify transfer_data(). - if self._put_message_waiter is not None: - self._put_message_waiter.set_result(None) - self._put_message_waiter = None - - return message - - async def send( - self, message: Union[Data, Iterable[Data], AsyncIterable[Data]] - ) -> None: - """ - Send a message. - - A string (:class:`str`) is sent as a `Text frame`_. A bytestring or - bytes-like object (:class:`bytes`, :class:`bytearray`, or - :class:`memoryview`) is sent as a `Binary frame`_. - - .. _Text frame: https://tools.ietf.org/html/rfc6455#section-5.6 - .. _Binary frame: https://tools.ietf.org/html/rfc6455#section-5.6 - - :meth:`send` also accepts an iterable or an asynchronous iterable of - strings, bytestrings, or bytes-like objects. In that case the message - is fragmented. Each item is treated as a message fragment and sent in - its own frame. All items must be of the same type, or else - :meth:`send` will raise a :exc:`TypeError` and the connection will be - closed. - - Canceling :meth:`send` is discouraged. Instead, you should close the - connection with :meth:`close`. Indeed, there only two situations where - :meth:`send` yields control to the event loop: - - 1. The write buffer is full. If you don't want to wait until enough - data is sent, your only alternative is to close the connection. - :meth:`close` will likely time out then abort the TCP connection. - 2. ``message`` is an asynchronous iterator. Stopping in the middle of - a fragmented message will cause a protocol error. Closing the - connection has the same effect. - - :raises TypeError: for unsupported inputs - """ - await self.ensure_open() + # Don't yield from self.ensure_open() here because messages could be + # available in the queue even if the connection is closed. - # While sending a fragmented message, prevent sending other messages - # until all fragments are sent. - while self._fragmented_message_waiter is not None: - await asyncio.shield(self._fragmented_message_waiter) - - # Unfragmented message -- this case must be handled first because - # strings and bytes-like objects are iterable. - - if isinstance(message, (str, bytes, bytearray, memoryview)): - opcode, data = prepare_data(message) - await self.write_frame(True, opcode, data) - - # Fragmented message -- regular iterator. - - elif isinstance(message, Iterable): - - # Work around https://github.com/python/mypy/issues/6227 - message = cast(Iterable[Data], message) - - iter_message = iter(message) - try: - message_chunk = next(iter_message) - except StopIteration: - return - opcode, data = prepare_data(message_chunk) - - self._fragmented_message_waiter = asyncio.Future() - try: - # First fragment. - await self.write_frame(False, opcode, data) - - # Other fragments. - for message_chunk in iter_message: - confirm_opcode, data = prepare_data(message_chunk) - if confirm_opcode != opcode: - raise TypeError("data contains inconsistent types") - await self.write_frame(False, OP_CONT, data) - - # Final fragment. - await self.write_frame(True, OP_CONT, b"") - - except Exception: - # We're half-way through a fragmented message and we can't - # complete it. This makes the connection unusable. - self.fail_connection(1011) - raise - - finally: - self._fragmented_message_waiter.set_result(None) - self._fragmented_message_waiter = None - - # Fragmented message -- asynchronous iterator - - elif isinstance(message, AsyncIterable): - # aiter_message = aiter(message) without aiter - # https://github.com/python/mypy/issues/5738 - aiter_message = type(message).__aiter__(message) # type: ignore - try: - # message_chunk = anext(aiter_message) without anext - # https://github.com/python/mypy/issues/5738 - message_chunk = await type(aiter_message).__anext__( # type: ignore - aiter_message - ) - except StopAsyncIteration: - return - opcode, data = prepare_data(message_chunk) - - self._fragmented_message_waiter = asyncio.Future() - try: - # First fragment. - await self.write_frame(False, opcode, data) - - # Other fragments. - # https://github.com/python/mypy/issues/5738 - async for message_chunk in aiter_message: # type: ignore - confirm_opcode, data = prepare_data(message_chunk) - if confirm_opcode != opcode: - raise TypeError("data contains inconsistent types") - await self.write_frame(False, OP_CONT, data) + # Return any available message + try: + return self.messages.get_nowait() + except asyncio.queues.QueueEmpty: + pass - # Final fragment. - await self.write_frame(True, OP_CONT, b"") + # Don't yield from self.ensure_open() here because messages could be + # received before the closing frame even if the connection is closing. - except Exception: - # We're half-way through a fragmented message and we can't - # complete it. This makes the connection unusable. - self.fail_connection(1011) - raise + # Wait for a message until the connection is closed + next_message = asyncio_ensure_future( + self.messages.get(), loop=self.loop) + try: + done, pending = yield from asyncio.wait( + [next_message, self.worker_task], + loop=self.loop, return_when=asyncio.FIRST_COMPLETED) + except asyncio.CancelledError: + # Handle the Task.cancel() + next_message.cancel() + raise - finally: - self._fragmented_message_waiter.set_result(None) - self._fragmented_message_waiter = None + # Now there's no need to yield from self.ensure_open(). Either a + # message was received or the connection was closed. + if next_message in done: + return next_message.result() else: - raise TypeError("data must be bytes, str, or iterable") + next_message.cancel() + if not self.legacy_recv: + raise ConnectionClosed(self.close_code, self.close_reason) - async def close(self, code: int = 1000, reason: str = "") -> None: + @asyncio.coroutine + def send(self, data): """ - Perform the closing handshake. - - :meth:`close` waits for the other end to complete the handshake and - for the TCP connection to terminate. As a consequence, there's no need - to await :meth:`wait_closed`; :meth:`close` already does it. + This coroutine sends a message. - :meth:`close` is idempotent: it doesn't do anything once the - connection is closed. - - Wrapping :func:`close` in :func:`~asyncio.create_task` is safe, given - that errors during connection termination aren't particularly useful. - - Canceling :meth:`close` is discouraged. If it takes too long, you can - set a shorter ``close_timeout``. If you don't want to wait, let the - Python process exit, then the OS will close the TCP connection. - - :param code: WebSocket close code - :param reason: WebSocket close reason + It sends :class:`str` as a text frame and :class:`bytes` as a binary + frame. It raises a :exc:`TypeError` for other inputs. """ - try: - await asyncio.wait_for( - self.write_close_frame(serialize_close(code, reason)), - self.close_timeout, - loop=self.loop if sys.version_info[:2] < (3, 8) else None, - ) - except asyncio.TimeoutError: - # If the close frame cannot be sent because the send buffers - # are full, the closing handshake won't complete anyway. - # Fail the connection to shut down faster. - self.fail_connection() - - # If no close frame is received within the timeout, wait_for() cancels - # the data transfer task and raises TimeoutError. + yield from self.ensure_open() - # If close() is called multiple times concurrently and one of these - # calls hits the timeout, the data transfer task will be cancelled. - # Other calls will receive a CancelledError here. - - try: - # If close() is canceled during the wait, self.transfer_data_task - # is canceled before the timeout elapses. - await asyncio.wait_for( - self.transfer_data_task, - self.close_timeout, - loop=self.loop if sys.version_info[:2] < (3, 8) else None, - ) - except (asyncio.TimeoutError, asyncio.CancelledError): - pass + if isinstance(data, str): + opcode = 1 + data = data.encode('utf-8') + elif isinstance(data, bytes): + opcode = 2 + else: + raise TypeError("data must be bytes or str") - # Wait for the close connection task to close the TCP connection. - await asyncio.shield(self.close_connection_task) + yield from self.write_frame(opcode, data) - async def ping(self, data: Optional[Data] = None) -> Awaitable[None]: + @asyncio.coroutine + def ping(self, data=None): """ - Send a ping. + This coroutine sends a ping. - Return a :class:`~asyncio.Future` which will be completed when the + It returns a :class:`~asyncio.Future` which will be completed when the corresponding pong is received and which you may ignore if you don't want to wait. A ping may serve as a keepalive or as a check that the remote endpoint - received all messages up to this point:: - - pong_waiter = await ws.ping() - await pong_waiter # only if you want to wait for the pong - - By default, the ping contains four random bytes. This payload may be - overridden with the optional ``data`` argument which must be a string - (which will be encoded to UTF-8) or a bytes-like object. + received all messages up to this point, with ``yield from ws.ping()``. - Canceling :meth:`ping` is discouraged. If :meth:`ping` doesn't return - immediately, it means the write buffer is full. If you don't want to - wait, you should close the connection. - - Canceling the :class:`~asyncio.Future` returned by :meth:`ping` has no - effect. + By default, the ping contains four random bytes. The content may be + overridden with the optional ``data`` argument which must be of type + :class:`str` (which will be encoded to UTF-8) or :class:`bytes`. """ - await self.ensure_open() + yield from self.ensure_open() if data is not None: - data = encode_data(data) + data = self.encode_data(data) # Protect against duplicates if a payload is explicitly set. if data in self.pings: - raise ValueError("already waiting for a pong with the same data") + raise ValueError("Already waiting for a pong with the same data") # Generate a unique random payload otherwise. while data is None or data in self.pings: - data = struct.pack("!I", random.getrandbits(32)) - - self.pings[data] = self.loop.create_future() - - await self.write_frame(True, OP_PING, data) + data = struct.pack('!I', random.getrandbits(32)) - return asyncio.shield(self.pings[data]) + self.pings[data] = asyncio.Future(loop=self.loop) + yield from self.write_frame(OP_PING, data) + return self.pings[data] - async def pong(self, data: Data = b"") -> None: + @asyncio.coroutine + def pong(self, data=b''): """ - Send a pong. + This coroutine sends a pong. An unsolicited pong may serve as a unidirectional heartbeat. - The payload may be set with the optional ``data`` argument which must - be a string (which will be encoded to UTF-8) or a bytes-like object. - - Canceling :meth:`pong` is discouraged for the same reason as - :meth:`ping`. + The content may be overridden with the optional ``data`` argument + which must be of type :class:`str` (which will be encoded to UTF-8) or + :class:`bytes`. """ - await self.ensure_open() + yield from self.ensure_open() - data = encode_data(data) + data = self.encode_data(data) - await self.write_frame(True, OP_PONG, data) + yield from self.write_frame(OP_PONG, data) # Private methods - no guarantees. - def connection_closed_exc(self) -> ConnectionClosed: - exception: ConnectionClosed - if self.close_code == 1000 or self.close_code == 1001: - exception = ConnectionClosedOK(self.close_code, self.close_reason) + def encode_data(self, data): + # Expect str or bytes, return bytes. + if isinstance(data, str): + return data.encode('utf-8') + elif isinstance(data, bytes): + return data else: - exception = ConnectionClosedError(self.close_code, self.close_reason) - # Chain to the exception that terminated data transfer, if any. - exception.__cause__ = self.transfer_data_exc - return exception - - async def ensure_open(self) -> None: - """ - Check that the WebSocket connection is open. + raise TypeError("data must be bytes or str") - Raise :exc:`~websockets.exceptions.ConnectionClosed` if it isn't. + @asyncio.coroutine + def ensure_open(self): + # Raise a suitable exception if the connection isn't open. + # Handle cases from the most common to the least common. - """ - # Handle cases from most common to least common for performance. - if self.state is State.OPEN: - # If self.transfer_data_task exited without a closing handshake, - # self.close_connection_task may be closing the connection, going - # straight from OPEN to CLOSED. - if self.transfer_data_task.done(): - await asyncio.shield(self.close_connection_task) - raise self.connection_closed_exc() - else: - return + if self.state == OPEN: + return - if self.state is State.CLOSED: - raise self.connection_closed_exc() + if self.state == CLOSED: + raise ConnectionClosed(self.close_code, self.close_reason) - if self.state is State.CLOSING: - # If we started the closing handshake, wait for its completion to - # get the proper close code and reason. self.close_connection_task - # will complete within 4 or 5 * close_timeout after close(). The - # CLOSING state also occurs when failing the connection. In that - # case self.close_connection_task will complete even faster. - await asyncio.shield(self.close_connection_task) - raise self.connection_closed_exc() + # If the closing handshake is in progress, let it complete to get the + # proper close status and code. As an safety measure, the timeout is + # longer than the worst case (2 * self.timeout) but not unlimited. + if self.state == CLOSING: + yield from asyncio.wait_for( + self.worker_task, 3 * self.timeout, loop=self.loop) + raise ConnectionClosed(self.close_code, self.close_reason) # Control may only reach this point in buggy third-party subclasses. - assert self.state is State.CONNECTING - raise InvalidState("WebSocket connection isn't established yet") - - async def transfer_data(self) -> None: - """ - Read incoming messages and put them in a queue. - - This coroutine runs in a task until the closing handshake is started. - - """ - try: - while True: - message = await self.read_message() - - # Exit the loop when receiving a close frame. - if message is None: + assert self.state == CONNECTING + raise InvalidState("WebSocket connection isn't established yet.") + + @asyncio.coroutine + def run(self): + # This coroutine guarantees that the connection is closed at exit. + yield from self.opening_handshake + while not self.closing_handshake.done(): + try: + msg = yield from self.read_message() + if msg is None: break + yield from self.messages.put(msg) + except asyncio.CancelledError: + break + except WebSocketProtocolError: + yield from self.fail_connection(1002) + except asyncio.IncompleteReadError: + yield from self.fail_connection(1006) + except UnicodeDecodeError: + yield from self.fail_connection(1007) + except PayloadTooBig: + yield from self.fail_connection(1009) + except Exception: + yield from self.fail_connection(1011) + raise + yield from self.close_connection() - # Wait until there's room in the queue (if necessary). - if self.max_queue is not None: - while len(self.messages) >= self.max_queue: - self._put_message_waiter = self.loop.create_future() - try: - await asyncio.shield(self._put_message_waiter) - finally: - self._put_message_waiter = None - - # Put the message in the queue. - self.messages.append(message) - - # Notify recv(). - if self._pop_message_waiter is not None: - self._pop_message_waiter.set_result(None) - self._pop_message_waiter = None - - except asyncio.CancelledError as exc: - self.transfer_data_exc = exc - # If fail_connection() cancels this task, avoid logging the error - # twice and failing the connection again. - raise - - except ProtocolError as exc: - self.transfer_data_exc = exc - self.fail_connection(1002) - - except (ConnectionError, EOFError) as exc: - # Reading data with self.reader.readexactly may raise: - # - most subclasses of ConnectionError if the TCP connection - # breaks, is reset, or is aborted; - # - IncompleteReadError, a subclass of EOFError, if fewer - # bytes are available than requested. - self.transfer_data_exc = exc - self.fail_connection(1006) - - except UnicodeDecodeError as exc: - self.transfer_data_exc = exc - self.fail_connection(1007) - - except PayloadTooBig as exc: - self.transfer_data_exc = exc - self.fail_connection(1009) - - except Exception as exc: - # This shouldn't happen often because exceptions expected under - # regular circumstances are handled above. If it does, consider - # catching and handling more exceptions. - logger.error("Error in data transfer", exc_info=True) - - self.transfer_data_exc = exc - self.fail_connection(1011) - - async def read_message(self) -> Optional[Data]: - """ - Read a single message from the connection. - - Re-assemble data frames if the message is fragmented. - - Return ``None`` when the closing handshake is started. - - """ - frame = await self.read_data_frame(max_size=self.max_size) - - # A close frame was received. + @asyncio.coroutine + def read_message(self): + # Reassemble fragmented messages. + frame = yield from self.read_data_frame(max_size=self.max_size) if frame is None: - return None - + return if frame.opcode == OP_TEXT: text = True elif frame.opcode == OP_BINARY: text = False - else: # frame.opcode == OP_CONT - raise ProtocolError("unexpected opcode") + else: # frame.opcode == OP_CONT + raise WebSocketProtocolError("Unexpected opcode") # Shortcut for the common case - no fragmentation if frame.fin: - return frame.data.decode("utf-8") if text else frame.data + return frame.data.decode('utf-8') if text else frame.data # 5.4. Fragmentation - chunks: List[Data] = [] + chunks = [] max_size = self.max_size if text: - decoder_factory = codecs.getincrementaldecoder("utf-8") - decoder = decoder_factory(errors="strict") + decoder = codecs.getincrementaldecoder('utf-8')(errors='strict') if max_size is None: - - def append(frame: Frame) -> None: + def append(frame): nonlocal chunks chunks.append(decoder.decode(frame.data, frame.fin)) - else: - - def append(frame: Frame) -> None: + def append(frame): nonlocal chunks, max_size chunks.append(decoder.decode(frame.data, frame.fin)) - assert isinstance(max_size, int) max_size -= len(frame.data) - else: if max_size is None: - - def append(frame: Frame) -> None: + def append(frame): nonlocal chunks chunks.append(frame.data) - else: - - def append(frame: Frame) -> None: + def append(frame): nonlocal chunks, max_size chunks.append(frame.data) - assert isinstance(max_size, int) max_size -= len(frame.data) - append(frame) while not frame.fin: - frame = await self.read_data_frame(max_size=max_size) + frame = yield from self.read_data_frame(max_size=max_size) if frame is None: - raise ProtocolError("incomplete fragmented message") + raise WebSocketProtocolError("Incomplete fragmented message") if frame.opcode != OP_CONT: - raise ProtocolError("unexpected opcode") + raise WebSocketProtocolError("Unexpected opcode") append(frame) - # mypy cannot figure out that chunks have the proper type. - return ("" if text else b"").join(chunks) # type: ignore - - async def read_data_frame(self, max_size: Optional[int]) -> Optional[Frame]: - """ - Read a single data frame from the connection. - - Process control frames received before the next data frame. + return ('' if text else b'').join(chunks) - Return ``None`` if a close frame is encountered before any data frame. - - """ + @asyncio.coroutine + def read_data_frame(self, max_size): + # Deal with control frames automatically and return next data frame. # 6.2. Receiving Data while True: - frame = await self.read_frame(max_size) + frame = yield from self.read_frame(max_size) # 5.5. Control Frames if frame.opcode == OP_CLOSE: - # 7.1.5. The WebSocket Connection Close Code - # 7.1.6. The WebSocket Connection Close Reason - self.close_code, self.close_reason = parse_close(frame.data) - try: - # Echo the original data instead of re-serializing it with - # serialize_close() because that fails when the close frame - # is empty and parse_close() synthetizes a 1005 close code. - await self.write_close_frame(frame.data) - except ConnectionClosed: - # It doesn't really matter if the connection was closed - # before we could send back a close frame. - pass - return None + # Make sure the close frame is valid before echoing it. + code, reason = parse_close(frame.data) + if self.state == OPEN: + # 7.1.3. The WebSocket Closing Handshake is Started + yield from self.write_frame(OP_CLOSE, frame.data) + self.close_code, self.close_reason = code, reason + self.closing_handshake.set_result(True) + return elif frame.opcode == OP_PING: # Answer pings. - ping_hex = frame.data.hex() or "[empty]" - logger.debug( - "%s - received ping, sending pong: %s", self.side, ping_hex - ) - await self.pong(frame.data) + yield from self.pong(frame.data) elif frame.opcode == OP_PONG: - # Acknowledge pings on solicited pongs. + # Do not acknowledge pings on unsolicited pongs. if frame.data in self.pings: - logger.debug( - "%s - received solicited pong: %s", - self.side, - frame.data.hex() or "[empty]", - ) # Acknowledge all pings up to the one matching this pong. ping_id = None - ping_ids = [] - for ping_id, ping in self.pings.items(): - ping_ids.append(ping_id) - if not ping.done(): - ping.set_result(None) - if ping_id == frame.data: - break - else: # pragma: no cover - assert False, "ping_id is in self.pings" - # Remove acknowledged pings from self.pings. - for ping_id in ping_ids: - del self.pings[ping_id] - ping_ids = ping_ids[:-1] - if ping_ids: - pings_hex = ", ".join( - ping_id.hex() or "[empty]" for ping_id in ping_ids - ) - plural = "s" if len(ping_ids) > 1 else "" - logger.debug( - "%s - acknowledged previous ping%s: %s", - self.side, - plural, - pings_hex, - ) - else: - logger.debug( - "%s - received unsolicited pong: %s", - self.side, - frame.data.hex() or "[empty]", - ) + while ping_id != frame.data: + ping_id, waiter = self.pings.popitem(0) + if not waiter.cancelled(): + waiter.set_result(None) # 5.6. Data Frames else: return frame - async def read_frame(self, max_size: Optional[int]) -> Frame: - """ - Read a single frame from the connection. - - """ - frame = await Frame.read( - self.reader.readexactly, - mask=not self.is_client, - max_size=max_size, - extensions=self.extensions, - ) - logger.debug("%s < %r", self.side, frame) + @asyncio.coroutine + def read_frame(self, max_size): + is_masked = not self.is_client + frame = yield from read_frame( + self.reader.readexactly, is_masked, max_size=max_size) + side = 'client' if self.is_client else 'server' + logger.debug("%s << %s", side, frame) return frame - async def write_frame( - self, fin: bool, opcode: int, data: bytes, *, _expected_state: int = State.OPEN - ) -> None: + @asyncio.coroutine + def write_frame(self, opcode, data=b''): # Defensive assertion for protocol compliance. - if self.state is not _expected_state: # pragma: no cover - raise InvalidState( - f"Cannot write to a WebSocket in the {self.state.name} state" - ) - - frame = Frame(fin, opcode, data) - logger.debug("%s > %r", self.side, frame) - frame.write( - self.transport.write, mask=self.is_client, extensions=self.extensions - ) + if self.state != OPEN: # pragma: no cover + raise InvalidState("Cannot write to a WebSocket " + "in the {} state".format(self.state_name)) + + # Make sure no other frame will be sent after a close frame. Do this + # before yielding control to avoid sending more than one close frame. + if opcode == OP_CLOSE: + self.state = CLOSING + frame = Frame(True, opcode, data) + side = 'client' if self.is_client else 'server' + logger.debug("%s >> %s", side, frame) + is_masked = self.is_client + write_frame(frame, self.writer.write, is_masked) + + # Backport of the combined logic of: + # https://github.com/python/asyncio/pull/280 + # https://github.com/python/asyncio/pull/291 + # Remove when dropping support for Python < 3.6. + transport = self.writer._transport + if transport is not None: # pragma: no cover + # PR 291 added the is_closing method to transports shortly after + # PR 280 fixed the bug we're trying to work around in this block. + if not hasattr(transport, 'is_closing'): + # This emulates what is_closing would return if it existed. + try: + is_closing = transport._closing + except AttributeError: + is_closing = transport._closed + if is_closing: + yield try: # drain() cannot be called concurrently by multiple coroutines: # http://bugs.python.org/issue29930. Remove this lock when no # version of Python where this bugs exists is supported anymore. - async with self._drain_lock: + with (yield from self._drain_lock): # Handle flow control automatically. - await self._drain() + yield from self.writer.drain() except ConnectionError: # Terminate the connection if the socket died. - self.fail_connection() - # Wait until the connection is closed to raise ConnectionClosed - # with the correct code and reason. - await self.ensure_open() - - async def write_close_frame(self, data: bytes = b"") -> None: - """ - Write a close frame if and only if the connection state is OPEN. - - This dedicated coroutine must be used for writing close frames to - ensure that at most one close frame is sent on a given connection. - - """ - # Test and set the connection state before sending the close frame to - # avoid sending two frames in case of concurrent calls. - if self.state is State.OPEN: - # 7.1.3. The WebSocket Closing Handshake is Started - self.state = State.CLOSING - logger.debug("%s - state = CLOSING", self.side) - - # 7.1.2. Start the WebSocket Closing Handshake - await self.write_frame(True, OP_CLOSE, data, _expected_state=State.CLOSING) - - async def keepalive_ping(self) -> None: - """ - Send a Ping frame and wait for a Pong frame at regular intervals. - - This coroutine exits when the connection terminates and one of the - following happens: - - - :meth:`ping` raises :exc:`ConnectionClosed`, or - - :meth:`close_connection` cancels :attr:`keepalive_ping_task`. - - """ - if self.ping_interval is None: + yield from self.fail_connection(1006) + # And raise an exception, since the frame couldn't be sent. + raise ConnectionClosed(self.close_code, self.close_reason) + + @asyncio.coroutine + def close_connection(self, force=False): + # 7.1.1. Close the WebSocket Connection + if self.state == CLOSED: return - try: - while True: - await asyncio.sleep( - self.ping_interval, - loop=self.loop if sys.version_info[:2] < (3, 8) else None, - ) - - # ping() raises CancelledError if the connection is closed, - # when close_connection() cancels self.keepalive_ping_task. - - # ping() raises ConnectionClosed if the connection is lost, - # when connection_lost() calls abort_pings(). - - ping_waiter = await self.ping() - - if self.ping_timeout is not None: - try: - await asyncio.wait_for( - ping_waiter, - self.ping_timeout, - loop=self.loop if sys.version_info[:2] < (3, 8) else None, - ) - except asyncio.TimeoutError: - logger.debug("%s ! timed out waiting for pong", self.side) - self.fail_connection(1011) - break - - except asyncio.CancelledError: - raise - - except ConnectionClosed: - pass - - except Exception: - logger.warning("Unexpected exception in keepalive ping task", exc_info=True) - - async def close_connection(self) -> None: - """ - 7.1.1. Close the WebSocket Connection - - When the opening handshake succeeds, :meth:`connection_open` starts - this coroutine in a task. It waits for the data transfer phase to - complete then it closes the TCP connection cleanly. - - When the opening handshake fails, :meth:`fail_connection` does the - same. There's no data transfer phase in that case. - - """ - try: - # Wait for the data transfer phase to complete. - if hasattr(self, "transfer_data_task"): - try: - await self.transfer_data_task - except asyncio.CancelledError: - pass - - # Cancel the keepalive ping task. - if hasattr(self, "keepalive_ping_task"): - self.keepalive_ping_task.cancel() - - # A client should wait for a TCP close from the server. - if self.is_client and hasattr(self, "transfer_data_task"): - if await self.wait_for_connection_lost(): - return - logger.debug("%s ! timed out waiting for TCP close", self.side) - - # Half-close the TCP connection if possible (when there's no TLS). - if self.transport.can_write_eof(): - logger.debug("%s x half-closing TCP connection", self.side) - self.transport.write_eof() - - if await self.wait_for_connection_lost(): - return - logger.debug("%s ! timed out waiting for TCP close", self.side) - - finally: - # The try/finally ensures that the transport never remains open, - # even if this coroutine is canceled (for example). - - # If connection_lost() was called, the TCP connection is closed. - # However, if TLS is enabled, the transport still needs closing. - # Else asyncio complains: ResourceWarning: unclosed transport. - if self.connection_lost_waiter.done() and self.transport.is_closing(): - return - - # Close the TCP connection. Buffers are flushed asynchronously. - logger.debug("%s x closing TCP connection", self.side) - self.transport.close() - - if await self.wait_for_connection_lost(): - return - logger.debug("%s ! timed out waiting for TCP close", self.side) - - # Abort the TCP connection. Buffers are discarded. - logger.debug("%s x aborting TCP connection", self.side) - self.transport.abort() - - # connection_lost() is called quickly after aborting. - await self.wait_for_connection_lost() - - async def wait_for_connection_lost(self) -> bool: - """ - Wait until the TCP connection is closed or ``self.close_timeout`` elapses. - - Return ``True`` if the connection is closed and ``False`` otherwise. + # Defensive assertion for protocol compliance. + if self.state != CLOSING and not force: # pragma: no cover + raise InvalidState("Cannot close a WebSocket connection " + "in the {} state".format(self.state_name)) - """ - if not self.connection_lost_waiter.done(): + if self.is_client and not force: try: - await asyncio.wait_for( - asyncio.shield(self.connection_lost_waiter), - self.close_timeout, - loop=self.loop if sys.version_info[:2] < (3, 8) else None, - ) - except asyncio.TimeoutError: + yield from asyncio.wait_for( + self.connection_closed, self.timeout, loop=self.loop) + except (asyncio.CancelledError, asyncio.TimeoutError): pass - # Re-check self.connection_lost_waiter.done() synchronously because - # connection_lost() could run between the moment the timeout occurs - # and the moment this coroutine resumes running. - return self.connection_lost_waiter.done() - - def fail_connection(self, code: int = 1006, reason: str = "") -> None: - """ - 7.1.7. Fail the WebSocket Connection - - This requires: - - 1. Stopping all processing of incoming data, which means cancelling - :attr:`transfer_data_task`. The close code will be 1006 unless a - close frame was received earlier. - - 2. Sending a close frame with an appropriate code if the opening - handshake succeeded and the other side is likely to process it. - - 3. Closing the connection. :meth:`close_connection` takes care of - this once :attr:`transfer_data_task` exits after being canceled. - - (The specification describes these steps in the opposite order.) - - """ - logger.debug( - "%s ! failing %s WebSocket connection with code %d", - self.side, - self.state.name, - code, - ) - - # Cancel transfer_data_task if the opening handshake succeeded. - # cancel() is idempotent and ignored if the task is done already. - if hasattr(self, "transfer_data_task"): - self.transfer_data_task.cancel() - - # Send a close frame when the state is OPEN (a close frame was already - # sent if it's CLOSING), except when failing the connection because of - # an error reading from or writing to the network. - # Don't send a close frame if the connection is broken. - if code != 1006 and self.state is State.OPEN: - - frame_data = serialize_close(code, reason) - - # Write the close frame without draining the write buffer. - - # Keeping fail_connection() synchronous guarantees it can't - # get stuck and simplifies the implementation of the callers. - # Not drainig the write buffer is acceptable in this context. - - # This duplicates a few lines of code from write_close_frame() - # and write_frame(). - - self.state = State.CLOSING - logger.debug("%s - state = CLOSING", self.side) - - frame = Frame(True, OP_CLOSE, frame_data) - logger.debug("%s > %r", self.side, frame) - frame.write( - self.transport.write, mask=self.is_client, extensions=self.extensions - ) - - # Start close_connection_task if the opening handshake didn't succeed. - if not hasattr(self, "close_connection_task"): - self.close_connection_task = self.loop.create_task(self.close_connection()) - - def abort_pings(self) -> None: - """ - Raise ConnectionClosed in pending keepalive pings. - - They'll never receive a pong once the connection is closed. - - """ - assert self.state is State.CLOSED - exc = self.connection_closed_exc() - - for ping in self.pings.values(): - ping.set_exception(exc) - # If the exception is never retrieved, it will be logged when ping - # is garbage-collected. This is confusing for users. - # Given that ping is done (with an exception), canceling it does - # nothing, but it prevents logging the exception. - ping.cancel() - - if self.pings: - pings_hex = ", ".join(ping_id.hex() or "[empty]" for ping_id in self.pings) - plural = "s" if len(self.pings) > 1 else "" - logger.debug( - "%s - aborted pending ping%s: %s", self.side, plural, pings_hex - ) - - # asyncio.Protocol methods - - def connection_made(self, transport: asyncio.BaseTransport) -> None: - """ - Configure write buffer limits. - - The high-water limit is defined by ``self.write_limit``. - - The low-water limit currently defaults to ``self.write_limit // 4`` in - :meth:`~asyncio.WriteTransport.set_write_buffer_limits`, which should - be all right for reasonable use cases of this library. - - This is the earliest point where we can get hold of the transport, - which means it's the best point for configuring it. - """ - logger.debug("%s - event = connection_made(%s)", self.side, transport) - - transport = cast(asyncio.Transport, transport) - transport.set_write_buffer_limits(self.write_limit) - self.transport = transport - - # Copied from asyncio.StreamReaderProtocol - self.reader.set_transport(transport) - - def connection_lost(self, exc: Optional[Exception]) -> None: - """ - 7.1.4. The WebSocket Connection is Closed. - - """ - logger.debug("%s - event = connection_lost(%s)", self.side, exc) - self.state = State.CLOSED - logger.debug("%s - state = CLOSED", self.side) - if not hasattr(self, "close_code"): - self.close_code = 1006 - if not hasattr(self, "close_reason"): - self.close_reason = "" - logger.debug( - "%s x code = %d, reason = %s", - self.side, - self.close_code, - self.close_reason or "[no reason]", - ) - self.abort_pings() - # If self.connection_lost_waiter isn't pending, that's a bug, because: - # - it's set only here in connection_lost() which is called only once; - # - it must never be canceled. - self.connection_lost_waiter.set_result(None) - - if True: # pragma: no cover - - # Copied from asyncio.StreamReaderProtocol - if self.reader is not None: - if exc is None: - self.reader.feed_eof() - else: - self.reader.set_exception(exc) - - # Copied from asyncio.FlowControlMixin - # Wake up the writer if currently paused. - if not self._paused: + if self.state == CLOSED: return - waiter = self._drain_waiter - if waiter is None: - return - self._drain_waiter = None - if waiter.done(): - return - if exc is None: - waiter.set_result(None) - else: - waiter.set_exception(exc) - - def pause_writing(self) -> None: # pragma: no cover - assert not self._paused - self._paused = True - def resume_writing(self) -> None: # pragma: no cover - assert self._paused - self._paused = False - - waiter = self._drain_waiter - if waiter is not None: - self._drain_waiter = None - if not waiter.done(): - waiter.set_result(None) - - def data_received(self, data: bytes) -> None: - logger.debug("%s - event = data_received(<%d bytes>)", self.side, len(data)) - self.reader.feed_data(data) - - def eof_received(self) -> None: - """ - Close the transport after receiving EOF. - - The WebSocket protocol has its own closing handshake: endpoints close - the TCP or TLS connection after sending and receiving a close frame. + # Attempt to terminate the TCP connection properly. + # If the socket is already closed, this may crash. + try: + if self.writer.can_write_eof(): + self.writer.write_eof() + except Exception: # pragma: no cover + pass - As a consequence, they never need to write after receiving EOF, so - there's no reason to keep the transport open by returning ``True``. + self.writer.close() - Besides, that doesn't work on TLS connections. + try: + yield from asyncio.wait_for( + self.connection_closed, self.timeout, loop=self.loop) + except (asyncio.CancelledError, asyncio.TimeoutError): + pass - """ - logger.debug("%s - event = eof_received()", self.side) - self.reader.feed_eof() + @asyncio.coroutine + def fail_connection(self, code=1011, reason=''): + # 7.1.7. Fail the WebSocket Connection + logger.info("Failing the WebSocket connection: %d %s", code, reason) + if self.state == OPEN: + if code == 1006: + # Don't send a close frame if the connection is broken. Set + # the state to CLOSING to allow close_connection to proceed. + self.state = CLOSING + else: + frame_data = serialize_close(code, reason) + yield from self.write_frame(OP_CLOSE, frame_data) + if not self.closing_handshake.done(): + self.close_code, self.close_reason = code, reason + self.closing_handshake.set_result(False) + yield from self.close_connection() + + # asyncio StreamReaderProtocol methods + + def client_connected(self, reader, writer): + self.reader = reader + self.writer = writer + # Configure write buffer limit. + self.writer._transport.set_write_buffer_limits(self.write_limit) + # Start the task that handles incoming messages. + self.worker_task = asyncio_ensure_future(self.run(), loop=self.loop) + + def eof_received(self): + super().eof_received() + # Since Python 3.5, StreamReaderProtocol.eof_received() returns True + # to leave the transport open (http://bugs.python.org/issue24539). + # This is inappropriate for websockets for at least three reasons. + # 1. The use case is to read data until EOF with self.reader.read(-1). + # Since websockets is a TLV protocol, this never happens. + # 2. It doesn't work on SSL connections. A falsy value must be + # returned to have the same behavior on SSL and plain connections. + # 3. The websockets protocol has its own closing handshake. Endpoints + # close the TCP connection after sending a Close frame. + # As a consequence we revert to the previous, more useful behavior. + return + + def connection_lost(self, exc): + # 7.1.4. The WebSocket Connection is Closed + self.state = CLOSED + if not self.opening_handshake.done(): + self.opening_handshake.set_result(False) + if not self.closing_handshake.done(): + self.close_code, self.close_reason = 1006, '' + self.closing_handshake.set_result(False) + if not self.connection_closed.done(): + self.connection_closed.set_result(None) + # Close the transport in case close_connection() wasn't executed. + if self.writer is not None: + self.writer.close() + super().connection_lost(exc) diff --git a/venv/Lib/site-packages/websockets/py.typed b/venv/Lib/site-packages/websockets/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/venv/Lib/site-packages/websockets/py35/__init__.py b/venv/Lib/site-packages/websockets/py35/__init__.py new file mode 100644 index 00000000..9612d9dd --- /dev/null +++ b/venv/Lib/site-packages/websockets/py35/__init__.py @@ -0,0 +1,2 @@ +# This package contains code using async / await syntax added in Python 3.5. +# It cannot be imported on Python < 3.5 because it triggers syntax errors. diff --git a/venv/Lib/site-packages/websockets/py35/client.py b/venv/Lib/site-packages/websockets/py35/client.py new file mode 100644 index 00000000..5ab7af03 --- /dev/null +++ b/venv/Lib/site-packages/websockets/py35/client.py @@ -0,0 +1,21 @@ +class Connect: + """ + This class wraps :func:`~websockets.client.connect` on Python ≥ 3.5. + + This allows using it as an asynchronous context manager. + + """ + def __init__(self, *args, **kwargs): + self.client = self.__class__.__wrapped__(*args, **kwargs) + + async def __aenter__(self): + self.websocket = await self + return self.websocket + + async def __aexit__(self, exc_type, exc_value, traceback): + await self.websocket.close() + + def __await__(self): + return (yield from self.client) + + __iter__ = __await__ diff --git a/venv/Lib/site-packages/websockets/py35/client_server.py b/venv/Lib/site-packages/websockets/py35/client_server.py new file mode 100644 index 00000000..624824aa --- /dev/null +++ b/venv/Lib/site-packages/websockets/py35/client_server.py @@ -0,0 +1,43 @@ +# Tests containing Python 3.5+ syntax, extracted from test_client_server.py. +# To avoid test discovery, this module's name must not start with test_. + +import asyncio + +from ..client import * +from ..server import * +from ..test_client_server import handler + + +class ClientServerContextManager: + + def setUp(self): + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + + def tearDown(self): + self.loop.close() + + def test_client(self): + server = serve(handler, 'localhost', 8642) + self.server = self.loop.run_until_complete(server) + + async def run_client(): + async with connect('ws://localhost:8642/') as client: + await client.send("Hello!") + reply = await client.recv() + self.assertEqual(reply, "Hello!") + + self.loop.run_until_complete(run_client()) + + self.server.close() + self.loop.run_until_complete(self.server.wait_closed()) + + def test_server(self): + async def run_server(): + async with serve(handler, 'localhost', 8642): + client = await connect('ws://localhost:8642/') + await client.send("Hello!") + reply = await client.recv() + self.assertEqual(reply, "Hello!") + + self.loop.run_until_complete(run_server()) diff --git a/venv/Lib/site-packages/websockets/py35/server.py b/venv/Lib/site-packages/websockets/py35/server.py new file mode 100644 index 00000000..3aba1c84 --- /dev/null +++ b/venv/Lib/site-packages/websockets/py35/server.py @@ -0,0 +1,22 @@ +class Serve: + """ + This class wraps :func:`~websockets.server.serve` on Python ≥ 3.5. + + This allows using it as an asynchronous context manager. + + """ + def __init__(self, *args, **kwargs): + self.server = self.__class__.__wrapped__(*args, **kwargs) + + async def __aenter__(self): + self.server = await self + return self.server + + async def __aexit__(self, exc_type, exc_value, traceback): + self.server.close() + await self.server.wait_closed() + + def __await__(self): + return (yield from self.server) + + __iter__ = __await__ diff --git a/venv/Lib/site-packages/websockets/server.py b/venv/Lib/site-packages/websockets/server.py index 4f5e9e0e..770609c7 100644 --- a/venv/Lib/site-packages/websockets/server.py +++ b/venv/Lib/site-packages/websockets/server.py @@ -1,64 +1,33 @@ + """ -:mod:`websockets.server` defines the WebSocket server APIs. +The :mod:`websockets.server` module defines a simple WebSocket server API. """ import asyncio import collections.abc -import email.utils -import functools -import http import logging -import socket -import sys -import warnings -from types import TracebackType -from typing import ( - Any, - Awaitable, - Callable, - Generator, - List, - Optional, - Sequence, - Set, - Tuple, - Type, - Union, - cast, -) +from .compatibility import ( + BAD_REQUEST, FORBIDDEN, INTERNAL_SERVER_ERROR, SERVICE_UNAVAILABLE, + SWITCHING_PROTOCOLS, asyncio_ensure_future +) from .exceptions import ( - AbortHandshake, - InvalidHandshake, - InvalidHeader, - InvalidMessage, - InvalidOrigin, - InvalidUpgrade, - NegotiationError, + AbortHandshake, InvalidHandshake, InvalidMessage, InvalidOrigin ) -from .extensions.base import Extension, ServerExtensionFactory -from .extensions.permessage_deflate import ServerPerMessageDeflateFactory from .handshake import build_response, check_request -from .headers import build_extension, parse_extension, parse_subprotocol -from .http import USER_AGENT, Headers, HeadersLike, MultipleValuesError, read_request -from .protocol import WebSocketCommonProtocol -from .typing import ExtensionHeader, Origin, Subprotocol +from .http import USER_AGENT, build_headers, read_request +from .protocol import CONNECTING, OPEN, WebSocketCommonProtocol -__all__ = ["serve", "unix_serve", "WebSocketServerProtocol", "WebSocketServer"] +__all__ = ['serve', 'WebSocketServerProtocol'] logger = logging.getLogger(__name__) -HeadersLikeOrCallable = Union[HeadersLike, Callable[[str, Headers], HeadersLike]] - -HTTPResponse = Tuple[http.HTTPStatus, HeadersLike, bytes] - - class WebSocketServerProtocol(WebSocketCommonProtocol): """ - :class:`~asyncio.Protocol` subclass implementing a WebSocket server. + Complete WebSocket server implementation as an :class:`asyncio.Protocol`. This class inherits most of its methods from :class:`~websockets.protocol.WebSocketCommonProtocol`. @@ -67,148 +36,108 @@ class WebSocketServerProtocol(WebSocketCommonProtocol): Its support for HTTP responses is very limited. """ + state = CONNECTING - is_client = False - side = "server" - - def __init__( - self, - ws_handler: Callable[["WebSocketServerProtocol", str], Awaitable[Any]], - ws_server: "WebSocketServer", - *, - origins: Optional[Sequence[Optional[Origin]]] = None, - extensions: Optional[Sequence[ServerExtensionFactory]] = None, - subprotocols: Optional[Sequence[Subprotocol]] = None, - extra_headers: Optional[HeadersLikeOrCallable] = None, - process_request: Optional[ - Callable[[str, Headers], Awaitable[Optional[HTTPResponse]]] - ] = None, - select_subprotocol: Optional[ - Callable[[Sequence[Subprotocol], Sequence[Subprotocol]], Subprotocol] - ] = None, - **kwargs: Any, - ) -> None: - # For backwards compatibility with 6.0 or earlier. - if origins is not None and "" in origins: - warnings.warn("use None instead of '' in origins", DeprecationWarning) - origins = [None if origin == "" else origin for origin in origins] + def __init__(self, ws_handler, ws_server, *, + origins=None, subprotocols=None, extra_headers=None, **kwds): self.ws_handler = ws_handler self.ws_server = ws_server self.origins = origins - self.available_extensions = extensions - self.available_subprotocols = subprotocols + self.subprotocols = subprotocols self.extra_headers = extra_headers - self._process_request = process_request - self._select_subprotocol = select_subprotocol - super().__init__(**kwargs) - - def connection_made(self, transport: asyncio.BaseTransport) -> None: - """ - Register connection and initialize a task to handle it. + super().__init__(**kwds) - """ + def connection_made(self, transport): super().connection_made(transport) - # Register the connection with the server before creating the handler - # task. Registering at the beginning of the handler coroutine would + # Register the connection with the server when creating the handler + # task. (Registering at the beginning of the handler coroutine would # create a race condition between the creation of the task, which - # schedules its execution, and the moment the handler starts running. + # schedules its execution, and the moment the handler starts running.) self.ws_server.register(self) - self.handler_task = self.loop.create_task(self.handler()) - - async def handler(self) -> None: - """ - Handle the lifecycle of a WebSocket connection. - - Since this method doesn't have a caller able to handle exceptions, it - attemps to log relevant ones and guarantees that the TCP connection is - closed before exiting. + self.handler_task = asyncio_ensure_future( + self.handler(), loop=self.loop) - """ + @asyncio.coroutine + def handler(self): + # Since this method doesn't have a caller able to handle exceptions, + # it attemps to log relevant ones and close the connection properly. try: try: - path = await self.handshake( - origins=self.origins, - available_extensions=self.available_extensions, - available_subprotocols=self.available_subprotocols, - extra_headers=self.extra_headers, - ) - except ConnectionError: - logger.debug("Connection error in opening handshake", exc_info=True) + path = yield from self.handshake( + origins=self.origins, subprotocols=self.subprotocols, + extra_headers=self.extra_headers) + except ConnectionError as exc: + logger.debug( + "Connection error in opening handshake", exc_info=True) raise except Exception as exc: - if isinstance(exc, AbortHandshake): - status, headers, body = exc.status, exc.headers, exc.body - elif isinstance(exc, InvalidOrigin): - logger.debug("Invalid origin", exc_info=True) - status, headers, body = ( - http.HTTPStatus.FORBIDDEN, - Headers(), - f"Failed to open a WebSocket connection: {exc}.\n".encode(), + if self._is_server_shutting_down(exc): + early_response = ( + SERVICE_UNAVAILABLE, + [], + b"Server is shutting down.", ) - elif isinstance(exc, InvalidUpgrade): - logger.debug("Invalid upgrade", exc_info=True) - status, headers, body = ( - http.HTTPStatus.UPGRADE_REQUIRED, - Headers([("Upgrade", "websocket")]), - ( - f"Failed to open a WebSocket connection: {exc}.\n" - f"\n" - f"You cannot access a WebSocket server directly " - f"with a browser. You need a WebSocket client.\n" - ).encode(), + elif isinstance(exc, AbortHandshake): + early_response = ( + exc.status, + exc.headers, + exc.body, + ) + elif isinstance(exc, InvalidOrigin): + logger.warning("Invalid origin", exc_info=True) + early_response = ( + FORBIDDEN, + [], + str(exc).encode(), ) elif isinstance(exc, InvalidHandshake): - logger.debug("Invalid handshake", exc_info=True) - status, headers, body = ( - http.HTTPStatus.BAD_REQUEST, - Headers(), - f"Failed to open a WebSocket connection: {exc}.\n".encode(), + logger.warning("Invalid handshake", exc_info=True) + early_response = ( + BAD_REQUEST, + [], + str(exc).encode(), ) else: logger.warning("Error in opening handshake", exc_info=True) - status, headers, body = ( - http.HTTPStatus.INTERNAL_SERVER_ERROR, - Headers(), - ( - b"Failed to open a WebSocket connection.\n" - b"See server log for more information.\n" - ), + early_response = ( + INTERNAL_SERVER_ERROR, + [], + b"See server log for more information.", ) - headers.setdefault("Date", email.utils.formatdate(usegmt=True)) - headers.setdefault("Server", USER_AGENT) - headers.setdefault("Content-Length", str(len(body))) - headers.setdefault("Content-Type", "text/plain") - headers.setdefault("Connection", "close") + yield from self.write_http_response(*early_response) + self.opening_handshake.set_result(False) + yield from self.close_connection(force=True) - self.write_http_response(status, headers, body) - self.fail_connection() - await self.wait_closed() return try: - await self.ws_handler(self, path) - except Exception: - logger.error("Error in connection handler", exc_info=True) - if not self.closed: - self.fail_connection(1011) + yield from self.ws_handler(self, path) + except Exception as exc: + if self._is_server_shutting_down(exc): + yield from self.fail_connection(1001) + else: + logger.error("Error in connection handler", exc_info=True) + yield from self.fail_connection(1011) raise try: - await self.close() - except ConnectionError: - logger.debug("Connection error in closing handshake", exc_info=True) + yield from self.close() + except ConnectionError as exc: + logger.debug( + "Connection error in closing handshake", exc_info=True) raise - except Exception: - logger.warning("Error in closing handshake", exc_info=True) + except Exception as exc: + if not self._is_server_shutting_down(exc): + logger.warning("Error in closing handshake", exc_info=True) raise except Exception: # Last-ditch attempt to avoid leaking connections on errors. try: - self.transport.close() - except Exception: # pragma: no cover + self.writer.close() + except Exception: # pragma: no cover pass finally: @@ -218,610 +147,353 @@ class WebSocketServerProtocol(WebSocketCommonProtocol): # connections before terminating. self.ws_server.unregister(self) - async def read_http_request(self) -> Tuple[str, Headers]: + def _is_server_shutting_down(self, exc): + """ + Decide whether an exception means that the server is shutting down. + + """ + return ( + isinstance(exc, asyncio.CancelledError) and + self.ws_server.closing + ) + + @asyncio.coroutine + def read_http_request(self): """ Read request line and headers from the HTTP request. - If the request contains a body, it may be read from ``self.reader`` - after this coroutine returns. + Raise :exc:`~websockets.exceptions.InvalidMessage` if the HTTP message + is malformed or isn't an HTTP/1.1 GET request. - :raises ~websockets.exceptions.InvalidMessage: if the HTTP message is - malformed or isn't an HTTP/1.1 GET request + Don't attempt to read the request body because WebSocket handshake + requests don't have one. If the request contains a body, it may be + read from ``self.reader`` after this coroutine returns. """ try: - path, headers = await read_request(self.reader) - except Exception as exc: - raise InvalidMessage("did not receive a valid HTTP request") from exc - - logger.debug("%s < GET %s HTTP/1.1", self.side, path) - logger.debug("%s < %r", self.side, headers) + path, headers = yield from read_request(self.reader) + except ValueError as exc: + raise InvalidMessage("Malformed HTTP message") from exc self.path = path - self.request_headers = headers + self.request_headers = build_headers(headers) + self.raw_request_headers = headers - return path, headers + return path, self.request_headers - def write_http_response( - self, status: http.HTTPStatus, headers: Headers, body: Optional[bytes] = None - ) -> None: + @asyncio.coroutine + def write_http_response(self, status, headers, body=None): """ Write status line and headers to the HTTP response. This coroutine is also able to write a response body. """ - self.response_headers = headers - - logger.debug("%s > HTTP/1.1 %d %s", self.side, status.value, status.phrase) - logger.debug("%s > %r", self.side, headers) + self.response_headers = build_headers(headers) + self.raw_response_headers = headers # Since the status line and headers only contain ASCII characters, # we can keep this simple. - response = f"HTTP/1.1 {status.value} {status.phrase}\r\n" - response += str(headers) + response = [ + 'HTTP/1.1 {value} {phrase}'.format( + value=status.value, phrase=status.phrase)] + response.extend('{}: {}'.format(k, v) for k, v in headers) + response.append('\r\n') + response = '\r\n'.join(response).encode() - self.transport.write(response.encode()) + self.writer.write(response) if body is not None: - logger.debug("%s > body (%d bytes)", self.side, len(body)) - self.transport.write(body) + self.writer.write(body) - async def process_request( - self, path: str, request_headers: Headers - ) -> Optional[HTTPResponse]: + @asyncio.coroutine + def process_request(self, path, request_headers): """ - Intercept the HTTP request and return an HTTP response if appropriate. - - If ``process_request`` returns ``None``, the WebSocket handshake - continues. If it returns 3-uple containing a status code, response - headers and a response body, that HTTP response is sent and the - connection is closed. In that case: + Intercept the HTTP request and return an HTTP response if needed. - * The HTTP status must be a :class:`~http.HTTPStatus`. - * HTTP headers must be a :class:`~websockets.http.Headers` instance, a - :class:`~collections.abc.Mapping`, or an iterable of ``(name, - value)`` pairs. - * The HTTP response body must be :class:`bytes`. It may be empty. + ``request_headers`` are a :class:`~http.client.HTTPMessage`. - This coroutine may be overridden in a :class:`WebSocketServerProtocol` - subclass, for example: + If this coroutine returns ``None``, the WebSocket handshake continues. + If it returns a status code, headers and a optionally a response body, + that HTTP response is sent and the connection is closed. - * to return a HTTP 200 OK response on a given path; then a load - balancer can use this path for a health check; - * to authenticate the request and return a HTTP 401 Unauthorized or a - HTTP 403 Forbidden when authentication fails. + The HTTP status must be a :class:`~http.HTTPStatus`. HTTP headers must + be an iterable of ``(name, value)`` pairs. If provided, the HTTP + response body must be :class:`bytes`. - Instead of subclassing, it is possible to override this method by - passing a ``process_request`` argument to the :func:`serve` function - or the :class:`WebSocketServerProtocol` constructor. This is - equivalent, except ``process_request`` won't have access to the - protocol instance, so it can't store information for later use. + (:class:`~http.HTTPStatus` was added in Python 3.5. Use a compatible + object on earlier versions. Look at ``SWITCHING_PROTOCOLS`` in + ``websockets.compatibility`` for an example.) - ``process_request`` is expected to complete quickly. If it may run for - a long time, then it should await :meth:`wait_closed` and exit if - :meth:`wait_closed` completes, or else it could prevent the server - from shutting down. + This method may be overridden to check the request headers and set a + different status, for example to authenticate the request and return + ``HTTPStatus.UNAUTHORIZED`` or ``HTTPStatus.FORBIDDEN``. - :param path: request path, including optional query string - :param request_headers: request headers + It is declared as a coroutine because such authentication checks are + likely to require network requests. """ - if self._process_request is not None: - response = self._process_request(path, request_headers) - if isinstance(response, Awaitable): - return await response - else: - # For backwards compatibility with 7.0. - warnings.warn( - "declare process_request as a coroutine", DeprecationWarning - ) - return response # type: ignore - return None - @staticmethod - def process_origin( - headers: Headers, origins: Optional[Sequence[Optional[Origin]]] = None - ) -> Optional[Origin]: + def process_origin(self, get_header, origins=None): """ - Handle the Origin HTTP request header. + Handle the Origin HTTP header. - :param headers: request headers - :param origins: optional list of acceptable origins - :raises ~websockets.exceptions.InvalidOrigin: if the origin isn't - acceptable + Raise :exc:`~websockets.exceptions.InvalidOrigin` if the origin isn't + acceptable. """ - # "The user agent MUST NOT include more than one Origin header field" - # per https://tools.ietf.org/html/rfc6454#section-7.3. - try: - origin = cast(Origin, headers.get("Origin")) - except MultipleValuesError: - raise InvalidHeader("Origin", "more than one Origin header found") + origin = get_header('Origin') if origins is not None: if origin not in origins: - raise InvalidOrigin(origin) + raise InvalidOrigin("Origin not allowed: {}".format(origin)) return origin - @staticmethod - def process_extensions( - headers: Headers, - available_extensions: Optional[Sequence[ServerExtensionFactory]], - ) -> Tuple[Optional[str], List[Extension]]: + def process_subprotocol(self, get_header, subprotocols=None): """ - Handle the Sec-WebSocket-Extensions HTTP request header. - - Accept or reject each extension proposed in the client request. - Negotiate parameters for accepted extensions. - - Return the Sec-WebSocket-Extensions HTTP response header and the list - of accepted extensions. - - :rfc:`6455` leaves the rules up to the specification of each - :extension. - - To provide this level of flexibility, for each extension proposed by - the client, we check for a match with each extension available in the - server configuration. If no match is found, the extension is ignored. - - If several variants of the same extension are proposed by the client, - it may be accepted severel times, which won't make sense in general. - Extensions must implement their own requirements. For this purpose, - the list of previously accepted extensions is provided. - - This process doesn't allow the server to reorder extensions. It can - only select a subset of the extensions proposed by the client. - - Other requirements, for example related to mandatory extensions or the - order of extensions, may be implemented by overriding this method. - - :param headers: request headers - :param extensions: optional list of supported extensions - :raises ~websockets.exceptions.InvalidHandshake: to abort the - handshake with an HTTP 400 error code + Handle the Sec-WebSocket-Protocol HTTP header. """ - response_header_value: Optional[str] = None - - extension_headers: List[ExtensionHeader] = [] - accepted_extensions: List[Extension] = [] - - header_values = headers.get_all("Sec-WebSocket-Extensions") - - if header_values and available_extensions: - - parsed_header_values: List[ExtensionHeader] = sum( - [parse_extension(header_value) for header_value in header_values], [] - ) - - for name, request_params in parsed_header_values: - - for ext_factory in available_extensions: - - # Skip non-matching extensions based on their name. - if ext_factory.name != name: - continue - - # Skip non-matching extensions based on their params. - try: - response_params, extension = ext_factory.process_request_params( - request_params, accepted_extensions - ) - except NegotiationError: - continue - - # Add matching extension to the final list. - extension_headers.append((name, response_params)) - accepted_extensions.append(extension) - - # Break out of the loop once we have a match. - break - - # If we didn't break from the loop, no extension in our list - # matched what the client sent. The extension is declined. - - # Serialize extension header. - if extension_headers: - response_header_value = build_extension(extension_headers) - - return response_header_value, accepted_extensions + if subprotocols is not None: + subprotocol = get_header('Sec-WebSocket-Protocol') + if subprotocol: + return self.select_subprotocol( + [p.strip() for p in subprotocol.split(',')], + subprotocols, + ) - # Not @staticmethod because it calls self.select_subprotocol() - def process_subprotocol( - self, headers: Headers, available_subprotocols: Optional[Sequence[Subprotocol]] - ) -> Optional[Subprotocol]: + @staticmethod + def select_subprotocol(client_protos, server_protos): """ - Handle the Sec-WebSocket-Protocol HTTP request header. - - Return Sec-WebSocket-Protocol HTTP response header, which is the same - as the selected subprotocol. - - :param headers: request headers - :param available_subprotocols: optional list of supported subprotocols - :raises ~websockets.exceptions.InvalidHandshake: to abort the - handshake with an HTTP 400 error code + Pick a subprotocol among those offered by the client. """ - subprotocol: Optional[Subprotocol] = None - - header_values = headers.get_all("Sec-WebSocket-Protocol") - - if header_values and available_subprotocols: - - parsed_header_values: List[Subprotocol] = sum( - [parse_subprotocol(header_value) for header_value in header_values], [] - ) - - subprotocol = self.select_subprotocol( - parsed_header_values, available_subprotocols - ) - - return subprotocol + common_protos = set(client_protos) & set(server_protos) + if not common_protos: + return None + priority = lambda p: client_protos.index(p) + server_protos.index(p) + return sorted(common_protos, key=priority)[0] - def select_subprotocol( - self, - client_subprotocols: Sequence[Subprotocol], - server_subprotocols: Sequence[Subprotocol], - ) -> Optional[Subprotocol]: + @asyncio.coroutine + def handshake(self, origins=None, subprotocols=None, extra_headers=None): """ - Pick a subprotocol among those offered by the client. + Perform the server side of the opening handshake. - If several subprotocols are supported by the client and the server, - the default implementation selects the preferred subprotocols by - giving equal value to the priorities of the client and the server. + If provided, ``origins`` is a list of acceptable HTTP Origin values. + Include ``''`` if the lack of an origin is acceptable. - If no subprotocol is supported by the client and the server, it - proceeds without a subprotocol. + If provided, ``subprotocols`` is a list of supported subprotocols in + order of decreasing preference. - This is unlikely to be the most useful implementation in practice, as - many servers providing a subprotocol will require that the client uses - that subprotocol. Such rules can be implemented in a subclass. + If provided, ``extra_headers`` sets additional HTTP response headers. + It can be a mapping or an iterable of (name, value) pairs. It can also + be a callable taking the request path and headers in arguments. - Instead of subclassing, it is possible to override this method by - passing a ``select_subprotocol`` argument to the :func:`serve` - function or the :class:`WebSocketServerProtocol` constructor + Raise :exc:`~websockets.exceptions.InvalidHandshake` or a subclass if + the handshake fails. - :param client_subprotocols: list of subprotocols offered by the client - :param server_subprotocols: list of subprotocols available on the server + Return the URI of the request. """ - if self._select_subprotocol is not None: - return self._select_subprotocol(client_subprotocols, server_subprotocols) - - subprotocols = set(client_subprotocols) & set(server_subprotocols) - if not subprotocols: - return None - priority = lambda p: ( - client_subprotocols.index(p) + server_subprotocols.index(p) - ) - return sorted(subprotocols, key=priority)[0] - - async def handshake( - self, - origins: Optional[Sequence[Optional[Origin]]] = None, - available_extensions: Optional[Sequence[ServerExtensionFactory]] = None, - available_subprotocols: Optional[Sequence[Subprotocol]] = None, - extra_headers: Optional[HeadersLikeOrCallable] = None, - ) -> str: - """ - Perform the server side of the opening handshake. - - Return the path of the URI of the request. - - :param origins: list of acceptable values of the Origin HTTP header; - include ``None`` if the lack of an origin is acceptable - :param available_extensions: list of supported extensions in the order - in which they should be used - :param available_subprotocols: list of supported subprotocols in order - of decreasing preference - :param extra_headers: sets additional HTTP response headers when the - handshake succeeds; it can be a :class:`~websockets.http.Headers` - instance, a :class:`~collections.abc.Mapping`, an iterable of - ``(name, value)`` pairs, or a callable taking the request path and - headers in arguments and returning one of the above. - :raises ~websockets.exceptions.InvalidHandshake: if the handshake - fails - - """ - path, request_headers = await self.read_http_request() + path, request_headers = yield from self.read_http_request() # Hook for customizing request handling, for example checking # authentication or treating some paths as plain HTTP endpoints. - early_response_awaitable = self.process_request(path, request_headers) - if isinstance(early_response_awaitable, Awaitable): - early_response = await early_response_awaitable - else: - # For backwards compatibility with 7.0. - warnings.warn("declare process_request as a coroutine", DeprecationWarning) - early_response = early_response_awaitable # type: ignore - - # Change the response to a 503 error if the server is shutting down. - if not self.ws_server.is_serving(): - early_response = ( - http.HTTPStatus.SERVICE_UNAVAILABLE, - [], - b"Server is shutting down.\n", - ) + early_response = yield from self.process_request(path, request_headers) if early_response is not None: raise AbortHandshake(*early_response) - key = check_request(request_headers) - - self.origin = self.process_origin(request_headers, origins) - - extensions_header, self.extensions = self.process_extensions( - request_headers, available_extensions - ) - - protocol_header = self.subprotocol = self.process_subprotocol( - request_headers, available_subprotocols - ) + get_header = lambda k: request_headers.get(k, '') - response_headers = Headers() + key = check_request(get_header) - build_response(response_headers, key) + self.origin = self.process_origin(get_header, origins) + self.subprotocol = self.process_subprotocol(get_header, subprotocols) - if extensions_header is not None: - response_headers["Sec-WebSocket-Extensions"] = extensions_header + response_headers = [] + set_header = lambda k, v: response_headers.append((k, v)) - if protocol_header is not None: - response_headers["Sec-WebSocket-Protocol"] = protocol_header + set_header('Server', USER_AGENT) - if callable(extra_headers): - extra_headers = extra_headers(path, self.request_headers) + if self.subprotocol: + set_header('Sec-WebSocket-Protocol', self.subprotocol) if extra_headers is not None: - if isinstance(extra_headers, Headers): - extra_headers = extra_headers.raw_items() - elif isinstance(extra_headers, collections.abc.Mapping): + if callable(extra_headers): + extra_headers = extra_headers(path, self.raw_request_headers) + if isinstance(extra_headers, collections.abc.Mapping): extra_headers = extra_headers.items() for name, value in extra_headers: - response_headers[name] = value + set_header(name, value) + build_response(set_header, key) - response_headers.setdefault("Date", email.utils.formatdate(usegmt=True)) - response_headers.setdefault("Server", USER_AGENT) + yield from self.write_http_response( + SWITCHING_PROTOCOLS, response_headers) - self.write_http_response(http.HTTPStatus.SWITCHING_PROTOCOLS, response_headers) - - self.connection_open() + assert self.state == CONNECTING + self.state = OPEN + self.opening_handshake.set_result(True) return path class WebSocketServer: """ - WebSocket server returned by :func:`~websockets.server.serve`. + Wraps an underlying :class:`~asyncio.Server` object. - This class provides the same interface as - :class:`~asyncio.AbstractServer`, namely the - :meth:`~asyncio.AbstractServer.close` and - :meth:`~asyncio.AbstractServer.wait_closed` methods. + This class provides the return type of :func:`~websockets.server.serve`. + This class shouldn't be instantiated directly. - It keeps track of WebSocket connections in order to close them properly - when shutting down. + Objects of this class store a reference to an underlying + :class:`~asyncio.Server` object returned by + :meth:`~asyncio.AbstractEventLoop.create_server`. The class stores a + reference rather than inheriting from :class:`~asyncio.Server` in part + because :meth:`~asyncio.AbstractEventLoop.create_server` doesn't support + passing a custom :class:`~asyncio.Server` class. - Instances of this class store a reference to the :class:`~asyncio.Server` - object returned by :meth:`~asyncio.loop.create_server` rather than inherit - from :class:`~asyncio.Server` in part because - :meth:`~asyncio.loop.create_server` doesn't support passing a custom - :class:`~asyncio.Server` class. + :class:`WebSocketServer` supports cleaning up the underlying + :class:`~asyncio.Server` object and other resources by implementing the + interface of ``asyncio.events.AbstractServer``, namely its ``close()`` + and ``wait_closed()`` methods. """ - - def __init__(self, loop: asyncio.AbstractEventLoop) -> None: + def __init__(self, loop): # Store a reference to loop to avoid relying on self.server._loop. self.loop = loop - # Keep track of active connections. - self.websockets: Set[WebSocketServerProtocol] = set() - - # Task responsible for closing the server and terminating connections. - self.close_task: Optional[asyncio.Task[None]] = None + self.closing = False + self.websockets = set() - # Completed when the server is closed and connections are terminated. - self.closed_waiter: asyncio.Future[None] = loop.create_future() - - def wrap(self, server: asyncio.AbstractServer) -> None: + def wrap(self, server): """ Attach to a given :class:`~asyncio.Server`. - Since :meth:`~asyncio.loop.create_server` doesn't support injecting a - custom ``Server`` class, the easiest solution that doesn't rely on - private :mod:`asyncio` APIs is to: + Since :meth:`~asyncio.AbstractEventLoop.create_server` doesn't support + injecting a custom ``Server`` class, a simple solution that doesn't + rely on private APIs is to: - instantiate a :class:`WebSocketServer` - give the protocol factory a reference to that instance - - call :meth:`~asyncio.loop.create_server` with the factory + - call :meth:`~asyncio.AbstractEventLoop.create_server` with the + factory - attach the resulting :class:`~asyncio.Server` with this method """ self.server = server - def register(self, protocol: WebSocketServerProtocol) -> None: - """ - Register a connection with this server. - - """ + def register(self, protocol): self.websockets.add(protocol) - def unregister(self, protocol: WebSocketServerProtocol) -> None: - """ - Unregister a connection with this server. - - """ + def unregister(self, protocol): self.websockets.remove(protocol) - def is_serving(self) -> bool: - """ - Tell whether the server is accepting new connections or shutting down. - - """ - try: - # Python ≥ 3.7 - return self.server.is_serving() - except AttributeError: # pragma: no cover - # Python < 3.7 - return self.server.sockets is not None - - def close(self) -> None: - """ - Close the server. - - This method: - - * closes the underlying :class:`~asyncio.Server`; - * rejects new WebSocket connections with an HTTP 503 (service - unavailable) error; this happens when the server accepted the TCP - connection but didn't complete the WebSocket opening handshake prior - to closing; - * closes open WebSocket connections with close code 1001 (going away). - - :meth:`close` is idempotent. - + def close(self): """ - if self.close_task is None: - self.close_task = self.loop.create_task(self._close()) - - async def _close(self) -> None: - """ - Implementation of :meth:`close`. + Close the underlying server, and clean up connections. This calls :meth:`~asyncio.Server.close` on the underlying - :class:`~asyncio.Server` object to stop accepting new connections and - then closes open connections with close code 1001. + :class:`~asyncio.Server` object, closes open connections with + status code 1001, and stops accepting new connections. """ + # Make a note that the server is shutting down. Websocket connections + # check this attribute to decide to send a "going away" close code. + self.closing = True + # Stop accepting new connections. self.server.close() - # Wait until self.server.close() completes. - await self.server.wait_closed() - - # Wait until all accepted connections reach connection_made() and call - # register(). See https://bugs.python.org/issue34852 for details. - await asyncio.sleep( - 0, loop=self.loop if sys.version_info[:2] < (3, 8) else None - ) - - # Close OPEN connections with status code 1001. Since the server was - # closed, handshake() closes OPENING conections with a HTTP 503 error. - # Wait until all connections are closed. - - # asyncio.wait doesn't accept an empty first argument - if self.websockets: - await asyncio.wait( - [websocket.close(1001) for websocket in self.websockets], - loop=self.loop if sys.version_info[:2] < (3, 8) else None, - ) - - # Wait until all connection handlers are complete. - - # asyncio.wait doesn't accept an empty first argument. - if self.websockets: - await asyncio.wait( - [websocket.handler_task for websocket in self.websockets], - loop=self.loop if sys.version_info[:2] < (3, 8) else None, - ) - - # Tell wait_closed() to return. - self.closed_waiter.set_result(None) - - async def wait_closed(self) -> None: - """ - Wait until the server is closed. - - When :meth:`wait_closed` returns, all TCP connections are closed and - all connection handlers have returned. + # Close open connections. For each connection, two tasks are running: + # 1. self.worker_task shuffles messages between the network and queues + # 2. self.handler_task runs the opening handshake, the handler provided + # by the user and the closing handshake + # In the general case, cancelling the handler task will cause the + # handler provided by the user to exit with a CancelledError, which + # will then cause the worker task to terminate. + for websocket in self.websockets: + websocket.handler_task.cancel() + @asyncio.coroutine + def wait_closed(self): """ - await asyncio.shield(self.closed_waiter) + Wait until the underlying server and all connections are closed. - @property - def sockets(self) -> Optional[List[socket.socket]]: - """ - List of :class:`~socket.socket` objects the server is listening to. + This calls :meth:`~asyncio.Server.wait_closed` on the underlying + :class:`~asyncio.Server` object and waits until closing handshakes + are complete and all connections are closed. - ``None`` if the server is closed. + This method must be called after :meth:`close()`. """ - return self.server.sockets - - -class Serve: + # asyncio.wait doesn't accept an empty first argument. + if self.websockets: + # The handler or the worker task can terminate first, depending + # on how the client behaves and the server is implemented. + yield from asyncio.wait( + [websocket.handler_task for websocket in self.websockets] + + [websocket.worker_task for websocket in self.websockets], + loop=self.loop) + yield from self.server.wait_closed() + + +@asyncio.coroutine +def serve(ws_handler, host=None, port=None, *, + create_protocol=None, + timeout=10, max_size=2 ** 20, max_queue=2 ** 5, + read_limit=2 ** 16, write_limit=2 ** 16, + loop=None, legacy_recv=False, klass=None, + origins=None, subprotocols=None, extra_headers=None, + **kwds): """ + Create, start, and return a :class:`WebSocketServer` object. - Create, start, and return a WebSocket server on ``host`` and ``port``. - - Whenever a client connects, the server accepts the connection, creates a - :class:`WebSocketServerProtocol`, performs the opening handshake, and - delegates to the connection handler defined by ``ws_handler``. Once the - handler completes, either normally or with an exception, the server - performs the closing handshake and closes the connection. - - Awaiting :func:`serve` yields a :class:`WebSocketServer`. This instance - provides :meth:`~websockets.server.WebSocketServer.close` and - :meth:`~websockets.server.WebSocketServer.wait_closed` methods for - terminating the server and cleaning up its resources. + :func:`serve` is a wrapper around the event loop's + :meth:`~asyncio.AbstractEventLoop.create_server` method. + Internally, the function creates and starts a :class:`~asyncio.Server` + object by calling :meth:`~asyncio.AbstractEventLoop.create_server`. The + :class:`WebSocketServer` keeps a reference to this object. - When a server is closed with :meth:`~WebSocketServer.close`, it closes all - connections with close code 1001 (going away). Connections handlers, which - are running the ``ws_handler`` coroutine, will receive a - :exc:`~websockets.exceptions.ConnectionClosedOK` exception on their - current or next interaction with the WebSocket connection. + The returned :class:`WebSocketServer` and its resources can be cleaned + up by calling its :meth:`~websockets.server.WebSocketServer.close` and + :meth:`~websockets.server.WebSocketServer.wait_closed` methods. - :func:`serve` can also be used as an asynchronous context manager. In - this case, the server is shut down when exiting the context. - - :func:`serve` is a wrapper around the event loop's - :meth:`~asyncio.loop.create_server` method. It creates and starts a - :class:`~asyncio.Server` with :meth:`~asyncio.loop.create_server`. Then it - wraps the :class:`~asyncio.Server` in a :class:`WebSocketServer` and - returns the :class:`WebSocketServer`. + On Python 3.5 and greater, :func:`serve` can also be used as an + asynchronous context manager. In this case, the server is shut down + when exiting the context. The ``ws_handler`` argument is the WebSocket handler. It must be a - coroutine accepting two arguments: a :class:`WebSocketServerProtocol` and - the request URI. + coroutine accepting two arguments: a :class:`WebSocketServerProtocol` + and the request URI. The ``host`` and ``port`` arguments, as well as unrecognized keyword - arguments, are passed along to :meth:`~asyncio.loop.create_server`. - - For example, you can set the ``ssl`` keyword argument to a - :class:`~ssl.SSLContext` to enable TLS. - - The ``create_protocol`` parameter allows customizing the - :class:`~asyncio.Protocol` that manages the connection. It should be a - callable or class accepting the same arguments as - :class:`WebSocketServerProtocol` and returning an instance of - :class:`WebSocketServerProtocol` or a subclass. It defaults to + arguments, are passed along to + :meth:`~asyncio.AbstractEventLoop.create_server`. For example, you can + set the ``ssl`` keyword argument to a :class:`~ssl.SSLContext` to enable + TLS. + + The ``create_protocol`` parameter allows customizing the asyncio protocol + that manages the connection. It should be a callable or class accepting + the same arguments as :class:`WebSocketServerProtocol` and returning a + :class:`WebSocketServerProtocol` instance. It defaults to :class:`WebSocketServerProtocol`. - The behavior of ``ping_interval``, ``ping_timeout``, ``close_timeout``, - ``max_size``, ``max_queue``, ``read_limit``, and ``write_limit`` is - described in :class:`~websockets.protocol.WebSocketCommonProtocol`. + The behavior of the ``timeout``, ``max_size``, and ``max_queue``, + ``read_limit``, and ``write_limit`` optional arguments is described in the + documentation of :class:`~websockets.protocol.WebSocketCommonProtocol`. :func:`serve` also accepts the following optional arguments: - * ``compression`` is a shortcut to configure compression extensions; - by default it enables the "permessage-deflate" extension; set it to - ``None`` to disable compression - * ``origins`` defines acceptable Origin HTTP headers; include ``None`` if - the lack of an origin is acceptable - * ``extensions`` is a list of supported extensions in order of - decreasing preference + * ``origins`` defines acceptable Origin HTTP headers — include + ``''`` if the lack of an origin is acceptable * ``subprotocols`` is a list of supported subprotocols in order of decreasing preference - * ``extra_headers`` sets additional HTTP response headers when the - handshake succeeds; it can be a :class:`~websockets.http.Headers` - instance, a :class:`~collections.abc.Mapping`, an iterable of ``(name, - value)`` pairs, or a callable taking the request path and headers in - arguments and returning one of the above - * ``process_request`` allows intercepting the HTTP request; it must be a - coroutine taking the request path and headers in argument; see - :meth:`~WebSocketServerProtocol.process_request` for details - * ``select_subprotocol`` allows customizing the logic for selecting a - subprotocol; it must be a callable taking the subprotocols offered by - the client and available on the server in argument; see - :meth:`~WebSocketServerProtocol.select_subprotocol` for details + * ``extra_headers`` sets additional HTTP response headers — it can be a + mapping, an iterable of (name, value) pairs, or a callable taking the + request path and headers in arguments. + + Whenever a client connects, the server accepts the connection, creates a + :class:`WebSocketServerProtocol`, performs the opening handshake, and + delegates to the WebSocket handler. Once the handler completes, the server + performs the closing handshake and closes the connection. Since there's no useful way to propagate exceptions triggered in handlers, they're sent to the ``'websockets.server'`` logger instead. Debugging is @@ -833,163 +505,42 @@ class Serve: logger.addHandler(logging.StreamHandler()) """ - - def __init__( - self, - ws_handler: Callable[[WebSocketServerProtocol, str], Awaitable[Any]], - host: Optional[Union[str, Sequence[str]]] = None, - port: Optional[int] = None, - *, - path: Optional[str] = None, - create_protocol: Optional[Type[WebSocketServerProtocol]] = None, - ping_interval: float = 20, - ping_timeout: float = 20, - close_timeout: Optional[float] = None, - max_size: int = 2 ** 20, - max_queue: int = 2 ** 5, - read_limit: int = 2 ** 16, - write_limit: int = 2 ** 16, - loop: Optional[asyncio.AbstractEventLoop] = None, - legacy_recv: bool = False, - klass: Optional[Type[WebSocketServerProtocol]] = None, - timeout: Optional[float] = None, - compression: Optional[str] = "deflate", - origins: Optional[Sequence[Optional[Origin]]] = None, - extensions: Optional[Sequence[ServerExtensionFactory]] = None, - subprotocols: Optional[Sequence[Subprotocol]] = None, - extra_headers: Optional[HeadersLikeOrCallable] = None, - process_request: Optional[ - Callable[[str, Headers], Awaitable[Optional[HTTPResponse]]] - ] = None, - select_subprotocol: Optional[ - Callable[[Sequence[Subprotocol], Sequence[Subprotocol]], Subprotocol] - ] = None, - **kwargs: Any, - ) -> None: - # Backwards compatibility: close_timeout used to be called timeout. - if timeout is None: - timeout = 10 - else: - warnings.warn("rename timeout to close_timeout", DeprecationWarning) - # If both are specified, timeout is ignored. - if close_timeout is None: - close_timeout = timeout - - # Backwards compatibility: create_protocol used to be called klass. - if klass is None: - klass = WebSocketServerProtocol - else: - warnings.warn("rename klass to create_protocol", DeprecationWarning) - # If both are specified, klass is ignored. - if create_protocol is None: - create_protocol = klass - - if loop is None: - loop = asyncio.get_event_loop() - - ws_server = WebSocketServer(loop) - - secure = kwargs.get("ssl") is not None - - if compression == "deflate": - if extensions is None: - extensions = [] - if not any( - ext_factory.name == ServerPerMessageDeflateFactory.name - for ext_factory in extensions - ): - extensions = list(extensions) + [ServerPerMessageDeflateFactory()] - elif compression is not None: - raise ValueError(f"unsupported compression: {compression}") - - factory = functools.partial( - create_protocol, - ws_handler, - ws_server, - host=host, - port=port, - secure=secure, - ping_interval=ping_interval, - ping_timeout=ping_timeout, - close_timeout=close_timeout, - max_size=max_size, - max_queue=max_queue, - read_limit=read_limit, - write_limit=write_limit, - loop=loop, - legacy_recv=legacy_recv, - origins=origins, - extensions=extensions, - subprotocols=subprotocols, - extra_headers=extra_headers, - process_request=process_request, - select_subprotocol=select_subprotocol, - ) - - if path is None: - create_server = functools.partial( - loop.create_server, factory, host, port, **kwargs - ) - else: - # unix_serve(path) must not specify host and port parameters. - assert host is None and port is None - create_server = functools.partial( - loop.create_unix_server, factory, path, **kwargs - ) - - # This is a coroutine function. - self._create_server = create_server - self.ws_server = ws_server - - # async with serve(...) - - async def __aenter__(self) -> WebSocketServer: - return await self - - async def __aexit__( - self, - exc_type: Optional[Type[BaseException]], - exc_value: Optional[BaseException], - traceback: Optional[TracebackType], - ) -> None: - self.ws_server.close() - await self.ws_server.wait_closed() - - # await serve(...) - - def __await__(self) -> Generator[Any, None, WebSocketServer]: - # Create a suitable iterator by calling __await__ on a coroutine. - return self.__await_impl__().__await__() - - async def __await_impl__(self) -> WebSocketServer: - server = await self._create_server() - self.ws_server.wrap(server) - return self.ws_server - - # yield from serve(...) - - __iter__ = __await__ - - -serve = Serve - - -def unix_serve( - ws_handler: Callable[[WebSocketServerProtocol, str], Awaitable[Any]], - path: str, - **kwargs: Any, -) -> Serve: - """ - Similar to :func:`serve`, but for listening on Unix sockets. - - This function calls the event loop's - :meth:`~asyncio.loop.create_unix_server` method. - - It is only available on Unix. - - It's useful for deploying a server behind a reverse proxy such as nginx. - - :param path: file system path to the Unix socket - - """ - return serve(ws_handler, path=path, **kwargs) + if loop is None: + loop = asyncio.get_event_loop() + + # Backwards-compatibility: create_protocol used to be called klass. + # In the unlikely event that both are specified, klass is ignored. + if create_protocol is None: + create_protocol = klass + + if create_protocol is None: + create_protocol = WebSocketServerProtocol + + ws_server = WebSocketServer(loop) + + secure = kwds.get('ssl') is not None + factory = lambda: create_protocol( + ws_handler, ws_server, + host=host, port=port, secure=secure, + timeout=timeout, max_size=max_size, max_queue=max_queue, + read_limit=read_limit, write_limit=write_limit, + loop=loop, legacy_recv=legacy_recv, + origins=origins, subprotocols=subprotocols, + extra_headers=extra_headers, + ) + server = yield from loop.create_server(factory, host, port, **kwds) + + ws_server.wrap(server) + + return ws_server + + +try: + from .py35.server import Serve +except (SyntaxError, ImportError): # pragma: no cover + pass +else: + Serve.__wrapped__ = serve + # Copy over docstring to support building documentation on Python 3.5. + Serve.__doc__ = serve.__doc__ + serve = Serve diff --git a/venv/Lib/site-packages/websockets/speedups.cp36-win_amd64.pyd b/venv/Lib/site-packages/websockets/speedups.cp36-win_amd64.pyd index 6fca6ea044654ff9c272129393042196ab0375ce..bb44fac7554fe9f991d186f80b02433a6b04b1ce 100644 GIT binary patch delta 3878 zcmd^C|5H@g6~AxY)#d9hUzYF60t>F#EQ^bX-;zbZJj`MMSBJzJSz(opxX^VO!9m#u zjo>S(c$-$7j0GokjI|S@Gbu^i=@LLtX$GCxXiYQNiHdEegEn#aq2uf4zW1>3OaFns znR7qqe9pP&oW1Y8d*24C163#1(LjQ_+iq{GI9L30!)W%%tfc($laYAXmY(Iq44Y5O zXz5ud*_NK1;Z(_Q8BPHnLtGrtFuHui3Vf?4eK=OaYzdF`+!~Q>vt(C#YU)@mB3~J# zyo8Y2w-=GzLp`r4B$+1Z#xPYRA<2XX4++tE?sb^+p0aO9*jMXMu|W46P9~wcL*V) z8b7_IUSnHtB!usZumGmSa6*m-o0d(Ls|h(0^c(puLxk*qmJ0tJ_(wI1=myPZZXNB` z*w$;&w(aiGV4K<&{71Ps)~R`#gTNgN@C%O5bQGHk+Sk{tM2oYfU(&+;Cen8XAry*(*jddYFeSO8#bzWThRv4 zBH{N2*|Hp_ZQ26vPjo=LIQgYymgO?L%{H;b7Ua8}rfOdJTr|8ur?vU2XGzo?vQ9Of zdwF+AG^hH;N)Lvvjs6lVboA=)SP5P6P={vJN=HLq!}6tt#c+1IGHj#e9=ddNmP|sX zbb1M=pXj0@?tp)y)0a)_qBOT8Ju2d_IrM|D8?k?3zmF}+kbMi^{;e^vUbN76!dG#> zpjX0ExdZe;c=htEc-C-90^eDp7Y%w?LXgj8`oH5Oy{pV9+uzV1MeMZy8WE&vp=hwd zJ-|9f3G>i6*5MhtpY%ofpCrc-yto zPDhfFZy(Z@uD#v*V0L2Z+B=8xbg4&BfE8!qtAy+A_ZH|rj!lqC=sphTR$MFWV6(*` ze(ifw!PYNIh0o*$XP1bsH!LkXH6x1S_O0yk<%Pdb4L%jc<7Ie(hmAWPwLbS*;o}8P z(DR)RleyDrGGZZfr$x~rlr#!k>v*B8dg}4_^drNom-Sh_T-#Txr3T3r1urOgyg=s9 zC^(?txPns(E>z-^6tpO~Nx@nL4=Q*e@az0OLJrWLojj6OyO4v^a(b9nIl08n@6P(ArE|nSs$8$*CESH-7 z+_1Q1n|*eavsUC4#GS%-0l0+!ayG`@1~+G=Uqo75cpQqc8!M9$g3C_G1S=@#Cljpc zg|K(+-_P9AcMa`M`l;$tDoszesII2c%H%bw`>FJu*9a+ZDe?JsZgKm!_xv4R`Al8uuP<^n`kQ?2q6RP96UbG@IT{-F zHZ^W+^49o04c-#3-`9eNjd`|teEud^{Z{V*kGGbP4>Vi7buMphy}K5r-Hj}Kqo>~Q zMs1G(LF4Bj*7KL7?GX6Ow60GWgy1bznzKxa4-OGrKRG2m(g{w_dY2W*0{TFnNW zZWk4U;h>@q1HV;thFqLHK@D_6Sm8S0DTQZvQPCNG4`EHr00;3A+7EpgxC8rH2lQ&- z5lCQVo2+~&83+W5icS&{Ra-;wV$+qcD&iYXmyOtB@Jo0*3b$onf*O{|_;lp$&3=B~IQo tm$J2Lv$@aO*U@*PFX629Y{6NivdjB7>C^Tl^x6A($=lm^nai5s{sUlUu6Y0e delta 4752 zcmd^DeNa@_6~Av`VOfL)VMV^*!V>Wd7Z(ZfBV7cNM_A%UNn(kXU0?~Td}VoC!5EhY zN!`4ViZ_|sOqv9f$(S~sI5D-PCY`mAfR;GKs5P-4rqe2ZOb4y8{E^P<@4oji&`kgA zU)`Dee&_zqx#ygF-o5u-=-J%k-nW)B46G{)<}L9)DQX$&umxprZdgJsT|{(dZ4Guc(xiiVU9TCRxnnffaxGD%~d?uP?6@RdGhMXcfe5@{>kojPEn!`24^b`}~M(-jW;F40Wb2FyE9ztw@ zi9$j$1}y0drXaj9OV6}!ZoraeED*h2A~c^R()qf(ig(Y0%!VQoS%5a{=ODyU(C868 z;CKTbAV?&dmA2{9qLc(&^iR5U`j#%4TS9-MTf{A+m+&m0@ex<|M;=f90x1*G_mTHv zqXT;Ty3NSgexWZMjI@WZx#Y2s{ys31TO*L;v(tOattGwdj;ta?Hxv3hNPlu0+=nt> zrd-rxT$pZ+y2SZtd34D7Y6fzVekYrshaj7qmG0QDV2qA>@udHCRU~+HRfPMk%OZp!&2Lu;2S>|vq5#_ATNQ?l7hrwqlq;&hrHvsUL= zd88?3KBp@xq&tmk<}bnm=sR(Yg)o&5@71Ri(oy4gQ9es-61R`8ioLI(5G8YlDlVc; zni3S8x@k&`TMYiDDWQ7Gl&H^BwM3;4J+vL^X}#@ z(~sw6bEEXqJonP0SVn?Wu}}zAB*^A5^rWy*$m9`K?yu(6{s;7lxH`v$6eJmllFe(N z9%30IME>wN>cF9DsD2t019(9S4uMyJRGIF6CTo)E~TF)l<1enlCxjnK}!`_ zUVoV`m%^3DFY?aVu+VpU_q|T(T%~lPdg-Tvd{Q`mHA0YoEA(e5C$%ZtL7JLO*?ZXJ zQL{*+5bUosRAPdm(rKahDi^pWtoid(mdd3!OxcJ$T-iS_wf7=?44aNd=C6#5-^;;Z z*WW576jqrzE9^Jbnf(UGh0qo&juO$D@F?41f^<`mJ{Keel%@sA{9*zo7hH4FwC8nX zBb$$+-xoIZy@;MuDl<6O=qac`?Ym_{e^rTW{!lRx;iwEJRun)GLecE)Y?*l_*wA&z zEbam3yWjj|wpP!2^n1tTZ(G*J@v3PzOsgfwLZ$pg|INHALFhXnve5b0qH#Q4FtGqE zd?<<~!j?tI#LktvVfxdgMb*={WqI83usZ*%la{Y!`Ppimu_OG}D}T77!-BdhNSu_Q ztn*L}Ti0;|f0t#aRM8_=<*mG;G$e zMni{&BloC&&TDv6!zfLkqoEcpNL*UL5)C_M645M9YyDdqCahHzLt4LF>u=QXO^rXG z;WCYXPU~xK$w4Ktc0!)fG88r3tYNu^HVrd0oTuTX64ljd4Z|89(r_lw*O{b;o!u@A zkXjx>&d3ViJDVqL|?AqI0t3T(E9rpF2CK%aeY z3(7XuST~oIGMg@qvuI>3BYWl;Rw{;j>5YX+!F_WyE=6--E~j{SZ4OtX*d3b7DRzg! zok7F`zk20j1!9F#`_`R1cQ)1|b8@~&Nj)A4vB6qdsyM`zFf}PSsj5^>jjEZN!__LG zrorvy;JQlxxLxFv)wjC1(vYJ=el zKL;T^n~Un7@aw@vp`b?Qm`k#3`f-b^dd`7AUieYLL7Lcf>3UU$qw52iN+ zqjV%{zs_bcMiQeKPxOs(q$i7zPtb}G#*!RGl522RgpT}&jx$9OQ)4tS6#-YqcCeT; zEAm~8MKSKQL+HPab{NeK-=~0tbav44jAaixW-a@p*do(5wG7OJ{g$x(2W||dnfdJm z*8^^H7Pkfa^)(wVVv@R>tYtbSxLJee&tV5pN zqPNuV_jK2JTRX(=x=uB(MQjRpRBQ~+ux_!rz0F=+(Ad&~zvm)1iY;ZH4l&^OvN^K9 z^1h(2W~G|HWSU2Oelg%_dAMzdudR`g59lXZ>G~)2m^nR_mAW`ncfVIG3;6xsHqqs8 zZ}4JYzND}5`dfW%n8yr7LUcuTI_IKQ*{RF3zCEV0k>t!`YnoAoMv!ER4rHftIrQh* z=_xG{m2E!J=V|fn^lozcIz<6SQSD~uz_2w8!~Y)XJnrQ?T_!iScRzzq8|nc*?C7r-<84DI}?0n37S w?=nQ@y9b*GhX%ug!a?`J=7UJpp?*1CgPWn*H+W$1{NTmGslg+OcTI5r2E^%{p#T5? diff --git a/venv/Lib/site-packages/websockets/test_client_server.py b/venv/Lib/site-packages/websockets/test_client_server.py new file mode 100644 index 00000000..ac020636 --- /dev/null +++ b/venv/Lib/site-packages/websockets/test_client_server.py @@ -0,0 +1,622 @@ +import asyncio +import contextlib +import functools +import logging +import os +import ssl +import sys +import unittest +import unittest.mock +import urllib.request + +from .client import * +from .compatibility import FORBIDDEN, OK, UNAUTHORIZED +from .exceptions import ConnectionClosed, InvalidHandshake, InvalidStatusCode +from .http import USER_AGENT, read_response +from .server import * + + +# Avoid displaying stack traces at the ERROR logging level. +logging.basicConfig(level=logging.CRITICAL) + +testcert = os.path.join(os.path.dirname(__file__), 'testcert.pem') + + +@asyncio.coroutine +def handler(ws, path): + if path == '/attributes': + yield from ws.send(repr((ws.host, ws.port, ws.secure))) + elif path == '/path': + yield from ws.send(str(ws.path)) + elif path == '/headers': + yield from ws.send(str(ws.request_headers)) + yield from ws.send(str(ws.response_headers)) + elif path == '/raw_headers': + yield from ws.send(repr(ws.raw_request_headers)) + yield from ws.send(repr(ws.raw_response_headers)) + elif path == '/subprotocol': + yield from ws.send(repr(ws.subprotocol)) + else: + yield from ws.send((yield from ws.recv())) + + +@contextlib.contextmanager +def temp_test_server(test, **kwds): + test.start_server(**kwds) + try: + yield + finally: + test.stop_server() + + +@contextlib.contextmanager +def temp_test_client(test, *args, **kwds): + test.start_client(*args, **kwds) + try: + yield + finally: + test.stop_client() + + +def with_manager(manager, *args, **kwds): + """ + Return a decorator that wraps a function with a context manager. + """ + def decorate(func): + @functools.wraps(func) + def _decorate(self, *_args, **_kwds): + with manager(self, *args, **kwds): + return func(self, *_args, **_kwds) + + return _decorate + + return decorate + + +def with_server(**kwds): + """ + Return a decorator for TestCase methods that starts and stops a server. + """ + return with_manager(temp_test_server, **kwds) + + +def with_client(*args, **kwds): + """ + Return a decorator for TestCase methods that starts and stops a client. + """ + return with_manager(temp_test_client, *args, **kwds) + + +class UnauthorizedServerProtocol(WebSocketServerProtocol): + + @asyncio.coroutine + def process_request(self, path, request_headers): + return UNAUTHORIZED, [] + + +class ForbiddenServerProtocol(WebSocketServerProtocol): + + @asyncio.coroutine + def process_request(self, path, request_headers): + return FORBIDDEN, [] + + +class HealthCheckServerProtocol(WebSocketServerProtocol): + + @asyncio.coroutine + def process_request(self, path, request_headers): + if path == '/__health__/': + body = b'status = green\n' + return OK, [('Content-Length', str(len(body)))], body + + +class FooClientProtocol(WebSocketClientProtocol): + pass + + +class BarClientProtocol(WebSocketClientProtocol): + pass + + +class ClientServerTests(unittest.TestCase): + + secure = False + + def setUp(self): + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + + def tearDown(self): + self.loop.close() + + def run_loop_once(self): + # Process callbacks scheduled with call_soon by appending a callback + # to stop the event loop then running it until it hits that callback. + self.loop.call_soon(self.loop.stop) + self.loop.run_forever() + + def start_server(self, **kwds): + server = serve(handler, 'localhost', 8642, **kwds) + self.server = self.loop.run_until_complete(server) + + def start_client(self, path='', **kwds): + client = connect('ws://localhost:8642/' + path, **kwds) + self.client = self.loop.run_until_complete(client) + + def stop_client(self): + try: + self.loop.run_until_complete( + asyncio.wait_for(self.client.worker_task, timeout=1)) + except asyncio.TimeoutError: # pragma: no cover + self.fail("Client failed to stop") + + def stop_server(self): + self.server.close() + try: + self.loop.run_until_complete( + asyncio.wait_for(self.server.wait_closed(), timeout=1)) + except asyncio.TimeoutError: # pragma: no cover + self.fail("Server failed to stop") + + @contextlib.contextmanager + def temp_server(self, **kwds): + with temp_test_server(self, **kwds): + yield + + @contextlib.contextmanager + def temp_client(self, *args, **kwds): + with temp_test_client(self, *args, **kwds): + yield + + @with_server() + @with_client() + def test_basic(self): + self.loop.run_until_complete(self.client.send("Hello!")) + reply = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(reply, "Hello!") + + @with_server() + def test_server_close_while_client_connected(self): + self.start_client() + + def test_explicit_event_loop(self): + with self.temp_server(loop=self.loop): + with self.temp_client(loop=self.loop): + self.loop.run_until_complete(self.client.send("Hello!")) + reply = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(reply, "Hello!") + + @with_server() + @with_client('attributes') + def test_protocol_attributes(self): + expected_attrs = ('localhost', 8642, self.secure) + client_attrs = (self.client.host, self.client.port, self.client.secure) + self.assertEqual(client_attrs, expected_attrs) + server_attrs = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(server_attrs, repr(expected_attrs)) + + @with_server() + @with_client('path') + def test_protocol_path(self): + client_path = self.client.path + self.assertEqual(client_path, '/path') + server_path = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(server_path, '/path') + + @with_server() + @with_client('headers') + def test_protocol_headers(self): + client_req = self.client.request_headers + client_resp = self.client.response_headers + self.assertEqual(client_req['User-Agent'], USER_AGENT) + self.assertEqual(client_resp['Server'], USER_AGENT) + server_req = self.loop.run_until_complete(self.client.recv()) + server_resp = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(server_req, str(client_req)) + self.assertEqual(server_resp, str(client_resp)) + + @with_server() + @with_client('raw_headers') + def test_protocol_raw_headers(self): + client_req = self.client.raw_request_headers + client_resp = self.client.raw_response_headers + self.assertEqual(dict(client_req)['User-Agent'], USER_AGENT) + self.assertEqual(dict(client_resp)['Server'], USER_AGENT) + server_req = self.loop.run_until_complete(self.client.recv()) + server_resp = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(server_req, repr(client_req)) + self.assertEqual(server_resp, repr(client_resp)) + + @with_server() + @with_client('raw_headers', extra_headers={'X-Spam': 'Eggs'}) + def test_protocol_custom_request_headers_dict(self): + req_headers = self.loop.run_until_complete(self.client.recv()) + self.loop.run_until_complete(self.client.recv()) + self.assertIn("('X-Spam', 'Eggs')", req_headers) + + @with_server() + @with_client('raw_headers', extra_headers=[('X-Spam', 'Eggs')]) + def test_protocol_custom_request_headers_list(self): + req_headers = self.loop.run_until_complete(self.client.recv()) + self.loop.run_until_complete(self.client.recv()) + self.assertIn("('X-Spam', 'Eggs')", req_headers) + + @with_server(extra_headers=lambda p, r: {'X-Spam': 'Eggs'}) + @with_client('raw_headers') + def test_protocol_custom_response_headers_callable_dict(self): + self.loop.run_until_complete(self.client.recv()) + resp_headers = self.loop.run_until_complete(self.client.recv()) + self.assertIn("('X-Spam', 'Eggs')", resp_headers) + + @with_server(extra_headers=lambda p, r: [('X-Spam', 'Eggs')]) + @with_client('raw_headers') + def test_protocol_custom_response_headers_callable_list(self): + self.loop.run_until_complete(self.client.recv()) + resp_headers = self.loop.run_until_complete(self.client.recv()) + self.assertIn("('X-Spam', 'Eggs')", resp_headers) + + @with_server(extra_headers={'X-Spam': 'Eggs'}) + @with_client('raw_headers') + def test_protocol_custom_response_headers_dict(self): + self.loop.run_until_complete(self.client.recv()) + resp_headers = self.loop.run_until_complete(self.client.recv()) + self.assertIn("('X-Spam', 'Eggs')", resp_headers) + + @with_server(extra_headers=[('X-Spam', 'Eggs')]) + @with_client('raw_headers') + def test_protocol_custom_response_headers_list(self): + self.loop.run_until_complete(self.client.recv()) + resp_headers = self.loop.run_until_complete(self.client.recv()) + self.assertIn("('X-Spam', 'Eggs')", resp_headers) + + @with_server(create_protocol=HealthCheckServerProtocol) + @with_client() + def test_custom_protocol_http_request(self): + # One URL returns an HTTP response. + + if self.secure: + url = 'https://localhost:8642/__health__/' + if sys.version_info[:2] < (3, 4): # pragma: no cover + # Python 3.3 didn't check SSL certificates. + open_health_check = functools.partial( + urllib.request.urlopen, url) + else: # pragma: no cover + open_health_check = functools.partial( + urllib.request.urlopen, url, context=self.client_context) + else: + url = 'http://localhost:8642/__health__/' + open_health_check = functools.partial( + urllib.request.urlopen, url) + + response = self.loop.run_until_complete( + self.loop.run_in_executor(None, open_health_check)) + + with contextlib.closing(response): + self.assertEqual(response.code, 200) + self.assertEqual(response.read(), b'status = green\n') + + # Other URLs create a WebSocket connection. + + self.loop.run_until_complete(self.client.send("Hello!")) + reply = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(reply, "Hello!") + + def assert_client_raises_code(self, status_code): + with self.assertRaises(InvalidStatusCode) as raised: + self.start_client() + self.assertEqual(raised.exception.status_code, status_code) + + @with_server(create_protocol=UnauthorizedServerProtocol) + def test_server_create_protocol(self): + self.assert_client_raises_code(401) + + @with_server(create_protocol=(lambda *args, **kwargs: + UnauthorizedServerProtocol(*args, **kwargs))) + def test_server_create_protocol_function(self): + self.assert_client_raises_code(401) + + @with_server(klass=UnauthorizedServerProtocol) + def test_server_klass(self): + self.assert_client_raises_code(401) + + @with_server(create_protocol=ForbiddenServerProtocol, + klass=UnauthorizedServerProtocol) + def test_server_create_protocol_over_klass(self): + self.assert_client_raises_code(403) + + @with_server() + @with_client('path', create_protocol=FooClientProtocol) + def test_client_create_protocol(self): + self.assertIsInstance(self.client, FooClientProtocol) + + @with_server() + @with_client('path', create_protocol=( + lambda *args, **kwargs: FooClientProtocol(*args, **kwargs))) + def test_client_create_protocol_function(self): + self.assertIsInstance(self.client, FooClientProtocol) + + @with_server() + @with_client('path', klass=FooClientProtocol) + def test_client_klass(self): + self.assertIsInstance(self.client, FooClientProtocol) + + @with_server() + @with_client('path', create_protocol=BarClientProtocol, + klass=FooClientProtocol) + def test_client_create_protocol_over_klass(self): + self.assertIsInstance(self.client, BarClientProtocol) + + @with_server() + @with_client('subprotocol') + def test_no_subprotocol(self): + server_subprotocol = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(server_subprotocol, repr(None)) + self.assertEqual(self.client.subprotocol, None) + + @with_server(subprotocols=['superchat', 'chat']) + @with_client('subprotocol', subprotocols=['otherchat', 'chat']) + def test_subprotocol_found(self): + server_subprotocol = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(server_subprotocol, repr('chat')) + self.assertEqual(self.client.subprotocol, 'chat') + + @with_server(subprotocols=['superchat']) + @with_client('subprotocol', subprotocols=['otherchat']) + def test_subprotocol_not_found(self): + server_subprotocol = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(server_subprotocol, repr(None)) + self.assertEqual(self.client.subprotocol, None) + + @with_server() + @with_client('subprotocol', subprotocols=['otherchat', 'chat']) + def test_subprotocol_not_offered(self): + server_subprotocol = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(server_subprotocol, repr(None)) + self.assertEqual(self.client.subprotocol, None) + + @with_server(subprotocols=['superchat', 'chat']) + @with_client('subprotocol') + def test_subprotocol_not_requested(self): + server_subprotocol = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(server_subprotocol, repr(None)) + self.assertEqual(self.client.subprotocol, None) + + @with_server(subprotocols=['superchat']) + @unittest.mock.patch.object(WebSocketServerProtocol, 'select_subprotocol') + def test_subprotocol_error(self, _select_subprotocol): + _select_subprotocol.return_value = 'superchat' + + with self.assertRaises(InvalidHandshake): + self.start_client('subprotocol', subprotocols=['otherchat']) + self.run_loop_once() + + @with_server() + @unittest.mock.patch('websockets.server.read_request') + def test_server_receives_malformed_request(self, _read_request): + _read_request.side_effect = ValueError("read_request failed") + + with self.assertRaises(InvalidHandshake): + self.start_client() + + @with_server() + @unittest.mock.patch('websockets.client.read_response') + def test_client_receives_malformed_response(self, _read_response): + _read_response.side_effect = ValueError("read_response failed") + + with self.assertRaises(InvalidHandshake): + self.start_client() + self.run_loop_once() + + @with_server() + @unittest.mock.patch('websockets.client.build_request') + def test_client_sends_invalid_handshake_request(self, _build_request): + def wrong_build_request(set_header): + return '42' + _build_request.side_effect = wrong_build_request + + with self.assertRaises(InvalidHandshake): + self.start_client() + + @with_server() + @unittest.mock.patch('websockets.server.build_response') + def test_server_sends_invalid_handshake_response(self, _build_response): + def wrong_build_response(set_header, key): + return build_response(set_header, '42') + _build_response.side_effect = wrong_build_response + + with self.assertRaises(InvalidHandshake): + self.start_client() + + @with_server() + @unittest.mock.patch('websockets.client.read_response') + def test_server_does_not_switch_protocols(self, _read_response): + @asyncio.coroutine + def wrong_read_response(stream): + status_code, headers = yield from read_response(stream) + return 400, headers + _read_response.side_effect = wrong_read_response + + with self.assertRaises(InvalidStatusCode): + self.start_client() + self.run_loop_once() + + @with_server() + @unittest.mock.patch('websockets.server.WebSocketServerProtocol.send') + def test_server_handler_crashes(self, send): + send.side_effect = ValueError("send failed") + + with self.temp_client(): + self.loop.run_until_complete(self.client.send("Hello!")) + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.client.recv()) + + # Connection ends with an unexpected error. + self.assertEqual(self.client.close_code, 1011) + + @with_server() + @unittest.mock.patch('websockets.server.WebSocketServerProtocol.close') + def test_server_close_crashes(self, close): + close.side_effect = ValueError("close failed") + + with self.temp_client(): + self.loop.run_until_complete(self.client.send("Hello!")) + reply = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(reply, "Hello!") + + # Connection ends with an abnormal closure. + self.assertEqual(self.client.close_code, 1006) + + @with_server() + @with_client() + @unittest.mock.patch.object(WebSocketClientProtocol, 'handshake') + def test_client_closes_connection_before_handshake(self, handshake): + # We have mocked the handshake() method to prevent the client from + # performing the opening handshake. Force it to close the connection. + self.loop.run_until_complete(self.client.close_connection(force=True)) + # The server should stop properly anyway. It used to hang because the + # worker handling the connection was waiting for the opening handshake. + + @with_server() + @unittest.mock.patch('websockets.server.read_request') + def test_server_shuts_down_during_opening_handshake(self, _read_request): + _read_request.side_effect = asyncio.CancelledError + + self.server.closing = True + with self.assertRaises(InvalidHandshake) as raised: + self.start_client() + + # Opening handshake fails with 503 Service Unavailable + self.assertEqual(str(raised.exception), "Status code not 101: 503") + + @with_server() + def test_server_shuts_down_during_connection_handling(self): + with self.temp_client(): + self.server.close() + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.client.recv()) + + # Websocket connection terminates with 1001 Going Away. + self.assertEqual(self.client.close_code, 1001) + + @with_server(create_protocol=ForbiddenServerProtocol) + def test_invalid_status_error_during_client_connect(self): + with self.assertRaises(InvalidStatusCode) as raised: + self.start_client() + exception = raised.exception + self.assertEqual(str(exception), "Status code not 101: 403") + self.assertEqual(exception.status_code, 403) + + @with_server() + @unittest.mock.patch('websockets.server.read_request') + def test_connection_error_during_opening_handshake(self, _read_request): + _read_request.side_effect = ConnectionError + + # Exception appears to be platform-dependent: InvalidHandshake on + # macOS, ConnectionResetError on Linux. This doesn't matter; this + # test primarily aims at covering a code path on the server side. + with self.assertRaises(Exception): + self.start_client() + + @with_server() + @unittest.mock.patch('websockets.server.WebSocketServerProtocol.close') + def test_connection_error_during_closing_handshake(self, close): + close.side_effect = ConnectionError + + with self.temp_client(): + self.loop.run_until_complete(self.client.send("Hello!")) + reply = self.loop.run_until_complete(self.client.recv()) + self.assertEqual(reply, "Hello!") + + # Connection ends with an abnormal closure. + self.assertEqual(self.client.close_code, 1006) + + +@unittest.skipUnless(os.path.exists(testcert), "test certificate is missing") +class SSLClientServerTests(ClientServerTests): + + secure = True + + @property + def server_context(self): + ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + ssl_context.load_cert_chain(testcert) + return ssl_context + + @property + def client_context(self): + ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + ssl_context.load_verify_locations(testcert) + ssl_context.verify_mode = ssl.CERT_REQUIRED + return ssl_context + + def start_server(self, *args, **kwds): + kwds['ssl'] = self.server_context + server = serve(handler, 'localhost', 8642, **kwds) + self.server = self.loop.run_until_complete(server) + + def start_client(self, path='', **kwds): + kwds['ssl'] = self.client_context + client = connect('wss://localhost:8642/' + path, **kwds) + self.client = self.loop.run_until_complete(client) + + @with_server() + def test_ws_uri_is_rejected(self): + client = connect('ws://localhost:8642/', ssl=self.client_context) + with self.assertRaises(ValueError): + self.loop.run_until_complete(client) + + +class ClientServerOriginTests(unittest.TestCase): + + def setUp(self): + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + + def tearDown(self): + self.loop.close() + + def test_checking_origin_succeeds(self): + server = self.loop.run_until_complete( + serve(handler, 'localhost', 8642, origins=['http://localhost'])) + client = self.loop.run_until_complete( + connect('ws://localhost:8642/', origin='http://localhost')) + + self.loop.run_until_complete(client.send("Hello!")) + self.assertEqual(self.loop.run_until_complete(client.recv()), "Hello!") + + self.loop.run_until_complete(client.close()) + server.close() + self.loop.run_until_complete(server.wait_closed()) + + def test_checking_origin_fails(self): + server = self.loop.run_until_complete( + serve(handler, 'localhost', 8642, origins=['http://localhost'])) + with self.assertRaisesRegex(InvalidHandshake, + "Status code not 101: 403"): + self.loop.run_until_complete( + connect('ws://localhost:8642/', origin='http://otherhost')) + + server.close() + self.loop.run_until_complete(server.wait_closed()) + + def test_checking_lack_of_origin_succeeds(self): + server = self.loop.run_until_complete( + serve(handler, 'localhost', 8642, origins=[''])) + client = self.loop.run_until_complete(connect('ws://localhost:8642/')) + + self.loop.run_until_complete(client.send("Hello!")) + self.assertEqual(self.loop.run_until_complete(client.recv()), "Hello!") + + self.loop.run_until_complete(client.close()) + server.close() + self.loop.run_until_complete(server.wait_closed()) + + +try: + from .py35.client_server import ClientServerContextManager +except (SyntaxError, ImportError): # pragma: no cover + pass +else: + class ClientServerContextManagerTests(ClientServerContextManager, + unittest.TestCase): + pass diff --git a/venv/Lib/site-packages/websockets/test_framing.py b/venv/Lib/site-packages/websockets/test_framing.py new file mode 100644 index 00000000..f88ee3bc --- /dev/null +++ b/venv/Lib/site-packages/websockets/test_framing.py @@ -0,0 +1,146 @@ +import asyncio +import unittest +import unittest.mock + +from .exceptions import PayloadTooBig, WebSocketProtocolError +from .framing import * + + +class FramingTests(unittest.TestCase): + + def setUp(self): + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + + def tearDown(self): + self.loop.close() + + def decode(self, message, mask=False, max_size=None): + self.stream = asyncio.StreamReader(loop=self.loop) + self.stream.feed_data(message) + self.stream.feed_eof() + frame = self.loop.run_until_complete(read_frame( + self.stream.readexactly, mask, max_size=max_size)) + # Make sure all the data was consumed. + self.assertTrue(self.stream.at_eof()) + return frame + + def encode(self, frame, mask=False): + writer = unittest.mock.Mock() + write_frame(frame, writer, mask) + # Ensure the entire frame is sent with a single call to writer(). + # Multiple calls cause TCP fragmentation and degrade performance. + self.assertEqual(writer.call_count, 1) + # The frame data is the single positional argument of that call. + return writer.call_args[0][0] + + def round_trip(self, message, expected, mask=False): + decoded = self.decode(message, mask) + self.assertEqual(decoded, expected) + encoded = self.encode(decoded, mask) + if mask: # non-deterministic encoding + decoded = self.decode(encoded, mask) + self.assertEqual(decoded, expected) + else: # deterministic encoding + self.assertEqual(encoded, message) + + def round_trip_close(self, data, code, reason): + parsed = parse_close(data) + self.assertEqual(parsed, (code, reason)) + serialized = serialize_close(code, reason) + self.assertEqual(serialized, data) + + def test_text(self): + self.round_trip(b'\x81\x04Spam', Frame(True, OP_TEXT, b'Spam')) + + def test_text_masked(self): + self.round_trip( + b'\x81\x84\x5b\xfb\xe1\xa8\x08\x8b\x80\xc5', + Frame(True, OP_TEXT, b'Spam'), mask=True) + + def test_binary(self): + self.round_trip(b'\x82\x04Eggs', Frame(True, OP_BINARY, b'Eggs')) + + def test_binary_masked(self): + self.round_trip( + b'\x82\x84\x53\xcd\xe2\x89\x16\xaa\x85\xfa', + Frame(True, OP_BINARY, b'Eggs'), mask=True) + + def test_non_ascii_text(self): + self.round_trip( + b'\x81\x05caf\xc3\xa9', + Frame(True, OP_TEXT, 'café'.encode('utf-8'))) + + def test_non_ascii_text_masked(self): + self.round_trip( + b'\x81\x85\x64\xbe\xee\x7e\x07\xdf\x88\xbd\xcd', + Frame(True, OP_TEXT, 'café'.encode('utf-8')), mask=True) + + def test_close(self): + self.round_trip(b'\x88\x00', Frame(True, OP_CLOSE, b'')) + + def test_ping(self): + self.round_trip(b'\x89\x04ping', Frame(True, OP_PING, b'ping')) + + def test_pong(self): + self.round_trip(b'\x8a\x04pong', Frame(True, OP_PONG, b'pong')) + + def test_long(self): + self.round_trip( + b'\x82\x7e\x00\x7e' + 126 * b'a', + Frame(True, OP_BINARY, 126 * b'a')) + + def test_very_long(self): + self.round_trip( + b'\x82\x7f\x00\x00\x00\x00\x00\x01\x00\x00' + 65536 * b'a', + Frame(True, OP_BINARY, 65536 * b'a')) + + def test_payload_too_big(self): + with self.assertRaises(PayloadTooBig): + self.decode(b'\x82\x7e\x04\x01' + 1025 * b'a', max_size=1024) + + def test_bad_reserved_bits(self): + with self.assertRaises(WebSocketProtocolError): + self.decode(b'\xc0\x00') + with self.assertRaises(WebSocketProtocolError): + self.decode(b'\xa0\x00') + with self.assertRaises(WebSocketProtocolError): + self.decode(b'\x90\x00') + + def test_bad_opcode(self): + for opcode in list(range(0x00, 0x03)) + list(range(0x08, 0x0b)): + self.decode(bytes([0x80 | opcode, 0])) + for opcode in list(range(0x03, 0x08)) + list(range(0x0b, 0x10)): + with self.assertRaises(WebSocketProtocolError): + self.decode(bytes([0x80 | opcode, 0])) + + def test_bad_mask_flag(self): + self.decode(b'\x80\x80\x00\x00\x00\x00', mask=True) + with self.assertRaises(WebSocketProtocolError): + self.decode(b'\x80\x80\x00\x00\x00\x00') + self.decode(b'\x80\x00') + with self.assertRaises(WebSocketProtocolError): + self.decode(b'\x80\x00', mask=True) + + def test_control_frame_too_long(self): + with self.assertRaises(WebSocketProtocolError): + self.decode(b'\x88\x7e\x00\x7e' + 126 * b'a') + + def test_fragmented_control_frame(self): + with self.assertRaises(WebSocketProtocolError): + self.decode(b'\x08\x00') + + def test_parse_close(self): + self.round_trip_close(b'\x03\xe8', 1000, '') + self.round_trip_close(b'\x03\xe8OK', 1000, 'OK') + + def test_parse_close_empty(self): + self.assertEqual(parse_close(b''), (1005, '')) + + def test_parse_close_errors(self): + with self.assertRaises(WebSocketProtocolError): + parse_close(b'\x03') + with self.assertRaises(WebSocketProtocolError): + parse_close(b'\x03\xe7') + with self.assertRaises(UnicodeDecodeError): + parse_close(b'\x03\xe8\xff\xff') diff --git a/venv/Lib/site-packages/websockets/test_handshake.py b/venv/Lib/site-packages/websockets/test_handshake.py new file mode 100644 index 00000000..2642d385 --- /dev/null +++ b/venv/Lib/site-packages/websockets/test_handshake.py @@ -0,0 +1,117 @@ +import contextlib +import unittest + +from .exceptions import InvalidHandshake +from .handshake import * +from .handshake import accept # private API + + +class HandshakeTests(unittest.TestCase): + + def test_accept(self): + # Test vector from RFC 6455 + key = "dGhlIHNhbXBsZSBub25jZQ==" + acc = "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=" + self.assertEqual(accept(key), acc) + + def test_round_trip(self): + request_headers = {} + request_key = build_request(request_headers.__setitem__) + response_key = check_request(request_headers.__getitem__) + self.assertEqual(request_key, response_key) + response_headers = {} + build_response(response_headers.__setitem__, response_key) + check_response(response_headers.__getitem__, request_key) + + @contextlib.contextmanager + def assert_invalid_request_headers(self): + """ + Provide request headers for corruption. + + Assert that the transformation made them invalid. + + """ + headers = {} + build_request(headers.__setitem__) + yield headers + with self.assertRaises(InvalidHandshake): + check_request(headers.__getitem__) + + def test_request_invalid_upgrade(self): + with self.assert_invalid_request_headers() as headers: + headers['Upgrade'] = 'socketweb' + + def test_request_missing_upgrade(self): + with self.assert_invalid_request_headers() as headers: + del headers['Upgrade'] + + def test_request_invalid_connection(self): + with self.assert_invalid_request_headers() as headers: + headers['Connection'] = 'Downgrade' + + def test_request_missing_connection(self): + with self.assert_invalid_request_headers() as headers: + del headers['Connection'] + + def test_request_invalid_key_not_base64(self): + with self.assert_invalid_request_headers() as headers: + headers['Sec-WebSocket-Key'] = "!@#$%^&*()" + + def test_request_invalid_key_not_well_padded(self): + with self.assert_invalid_request_headers() as headers: + headers['Sec-WebSocket-Key'] = "CSIRmL8dWYxeAdr/XpEHRw" + + def test_request_invalid_key_not_16_bytes_long(self): + with self.assert_invalid_request_headers() as headers: + headers['Sec-WebSocket-Key'] = "ZLpprpvK4PE=" + + def test_request_missing_key(self): + with self.assert_invalid_request_headers() as headers: + del headers['Sec-WebSocket-Key'] + + def test_request_invalid_version(self): + with self.assert_invalid_request_headers() as headers: + headers['Sec-WebSocket-Version'] = '42' + + def test_request_missing_version(self): + with self.assert_invalid_request_headers() as headers: + del headers['Sec-WebSocket-Version'] + + @contextlib.contextmanager + def assert_invalid_response_headers(self, key='CSIRmL8dWYxeAdr/XpEHRw=='): + """ + Provide response headers for corruption. + + Assert that the transformation made them invalid. + + """ + headers = {} + build_response(headers.__setitem__, key) + yield headers + with self.assertRaises(InvalidHandshake): + check_response(headers.__getitem__, key) + + def test_response_invalid_upgrade(self): + with self.assert_invalid_response_headers() as headers: + headers['Upgrade'] = 'socketweb' + + def test_response_missing_upgrade(self): + with self.assert_invalid_response_headers() as headers: + del headers['Upgrade'] + + def test_response_invalid_connection(self): + with self.assert_invalid_response_headers() as headers: + headers['Connection'] = 'Downgrade' + + def test_response_missing_connection(self): + with self.assert_invalid_response_headers() as headers: + del headers['Connection'] + + def test_response_invalid_accept(self): + with self.assert_invalid_response_headers() as headers: + other_key = "1Eq4UDEFQYg3YspNgqxv5g==" + headers['Sec-WebSocket-Accept'] = accept(other_key) + + def test_response_missing_accept(self): + with self.assert_invalid_response_headers() as headers: + del headers['Sec-WebSocket-Accept'] diff --git a/venv/Lib/site-packages/websockets/test_http.py b/venv/Lib/site-packages/websockets/test_http.py new file mode 100644 index 00000000..a891ad5e --- /dev/null +++ b/venv/Lib/site-packages/websockets/test_http.py @@ -0,0 +1,128 @@ +import asyncio +import unittest + +from .http import * +from .http import build_headers, read_headers + + +class HTTPAsyncTests(unittest.TestCase): + + def setUp(self): + super().setUp() + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + self.stream = asyncio.StreamReader(loop=self.loop) + + def tearDown(self): + self.loop.close() + super().tearDown() + + def test_read_request(self): + # Example from the protocol overview in RFC 6455 + self.stream.feed_data( + b'GET /chat HTTP/1.1\r\n' + b'Host: server.example.com\r\n' + b'Upgrade: websocket\r\n' + b'Connection: Upgrade\r\n' + b'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n' + b'Origin: http://example.com\r\n' + b'Sec-WebSocket-Protocol: chat, superchat\r\n' + b'Sec-WebSocket-Version: 13\r\n' + b'\r\n' + ) + path, hdrs = self.loop.run_until_complete(read_request(self.stream)) + self.assertEqual(path, '/chat') + self.assertEqual(dict(hdrs)['Upgrade'], 'websocket') + + def test_read_response(self): + # Example from the protocol overview in RFC 6455 + self.stream.feed_data( + b'HTTP/1.1 101 Switching Protocols\r\n' + b'Upgrade: websocket\r\n' + b'Connection: Upgrade\r\n' + b'Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n' + b'Sec-WebSocket-Protocol: chat\r\n' + b'\r\n' + ) + status_code, headers = self.loop.run_until_complete( + read_response(self.stream)) + self.assertEqual(status_code, 101) + self.assertEqual(dict(headers)['Upgrade'], 'websocket') + + def test_request_method(self): + self.stream.feed_data(b'OPTIONS * HTTP/1.1\r\n\r\n') + with self.assertRaises(ValueError): + self.loop.run_until_complete(read_request(self.stream)) + + def test_request_version(self): + self.stream.feed_data(b'GET /chat HTTP/1.0\r\n\r\n') + with self.assertRaises(ValueError): + self.loop.run_until_complete(read_request(self.stream)) + + def test_response_version(self): + self.stream.feed_data(b'HTTP/1.0 400 Bad Request\r\n\r\n') + with self.assertRaises(ValueError): + self.loop.run_until_complete(read_response(self.stream)) + + def test_response_status(self): + self.stream.feed_data(b'HTTP/1.1 007 My name is Bond\r\n\r\n') + with self.assertRaises(ValueError): + self.loop.run_until_complete(read_response(self.stream)) + + def test_response_reason(self): + self.stream.feed_data(b'HTTP/1.1 200 \x7f\r\n\r\n') + with self.assertRaises(ValueError): + self.loop.run_until_complete(read_response(self.stream)) + + def test_header_name(self): + self.stream.feed_data(b'foo bar: baz qux\r\n\r\n') + with self.assertRaises(ValueError): + self.loop.run_until_complete(read_headers(self.stream)) + + def test_header_value(self): + self.stream.feed_data(b'foo: \x00\x00\x0f\r\n\r\n') + with self.assertRaises(ValueError): + self.loop.run_until_complete(read_headers(self.stream)) + + def test_headers_limit(self): + self.stream.feed_data(b'foo: bar\r\n' * 500 + b'\r\n') + with self.assertRaises(ValueError): + self.loop.run_until_complete(read_headers(self.stream)) + + def test_line_limit(self): + self.stream.feed_data(b'a' * 5000 + b'\r\n\r\n') + with self.assertRaises(ValueError): + self.loop.run_until_complete(read_headers(self.stream)) + + def test_line_ending(self): + self.stream.feed_data(b'foo: bar\n\n') + with self.assertRaises(ValueError): + self.loop.run_until_complete(read_headers(self.stream)) + + +class HTTPSyncTests(unittest.TestCase): + + def test_build_headers(self): + headers = build_headers([ + ('X-Foo', 'Bar'), + ('X-Baz', 'Quux Quux'), + ]) + + self.assertEqual(headers['X-Foo'], 'Bar') + self.assertEqual(headers['X-Bar'], None) + + self.assertEqual(headers.get('X-Bar', ''), '') + self.assertEqual(headers.get('X-Baz', ''), 'Quux Quux') + + def test_build_headers_multi_value(self): + headers = build_headers([ + ('X-Foo', 'Bar'), + ('X-Foo', 'Baz'), + ]) + + # Getting a single value is non-deterministic. + self.assertIn(headers['X-Foo'], ['Bar', 'Baz']) + self.assertIn(headers.get('X-Foo'), ['Bar', 'Baz']) + + # Ordering is deterministic when getting all values. + self.assertEqual(headers.get_all('X-Foo'), ['Bar', 'Baz']) diff --git a/venv/Lib/site-packages/websockets/test_protocol.py b/venv/Lib/site-packages/websockets/test_protocol.py new file mode 100644 index 00000000..c08c57b4 --- /dev/null +++ b/venv/Lib/site-packages/websockets/test_protocol.py @@ -0,0 +1,789 @@ +import asyncio +import contextlib +import functools +import os +import time +import unittest +import unittest.mock + +from .compatibility import asyncio_ensure_future +from .exceptions import ConnectionClosed, InvalidState +from .framing import * +from .protocol import CLOSED, CONNECTING, WebSocketCommonProtocol + + +# Unit for timeouts. May be increased on slow machines by setting the +# WEBSOCKETS_TESTS_TIMEOUT_FACTOR environment variable. +MS = 0.001 * int(os.environ.get('WEBSOCKETS_TESTS_TIMEOUT_FACTOR', 1)) + +# asyncio's debug mode has a 10x performance penalty for this test suite. +if os.environ.get('PYTHONASYNCIODEBUG'): # pragma: no cover + MS *= 10 + +# Ensure that timeouts are larger than the clock's resolution (for Windows). +MS = max(MS, 2.5 * time.get_clock_info('monotonic').resolution) + + +class TransportMock(unittest.mock.Mock): + """ + Transport mock to control the protocol's inputs and outputs in tests. + + It calls the protocol's connection_made and connection_lost methods like + actual transports. + + To simulate incoming data, tests call the protocol's data_received and + eof_received methods directly. + + They could also pause_writing and resume_writing to test flow control. + + """ + # This should happen in __init__ but overriding Mock.__init__ is hard. + def connect(self, loop, protocol): + self.loop = loop + self.protocol = protocol + # Remove when dropping support for Python < 3.6. + self._closing = False + self.loop.call_soon(self.protocol.connection_made, self) + + def close(self): + # Remove when dropping support for Python < 3.6. + self._closing = True + self.loop.call_soon(self.protocol.connection_lost, None) + + +class CommonTests: + """ + Mixin that defines most tests but doesn't inherit unittest.TestCase. + + Tests are run by the ServerTests and ClientTests subclasses. + + """ + def setUp(self): + super().setUp() + self.loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.loop) + self.protocol = WebSocketCommonProtocol() + self.transport = TransportMock() + self.transport.connect(self.loop, self.protocol) + + def tearDown(self): + self.loop.run_until_complete( + self.protocol.close_connection(force=True)) + self.loop.close() + super().tearDown() + + # Utilities for writing tests. + + def run_loop_once(self): + # Process callbacks scheduled with call_soon by appending a callback + # to stop the event loop then running it until it hits that callback. + self.loop.call_soon(self.loop.stop) + self.loop.run_forever() + + def make_drain_slow(self): + # Process connection_made in order to initialize self.protocol.writer. + self.run_loop_once() + + original_drain = self.protocol.writer.drain + + @asyncio.coroutine + def delayed_drain(): + yield from asyncio.sleep(3 * MS, loop=self.loop) + yield from original_drain() + + self.protocol.writer.drain = delayed_drain + + close_frame = Frame(True, OP_CLOSE, serialize_close(1000, 'close')) + local_close = Frame(True, OP_CLOSE, serialize_close(1000, 'local')) + remote_close = Frame(True, OP_CLOSE, serialize_close(1000, 'remote')) + + @property + def ensure_future(self): + return functools.partial(asyncio_ensure_future, loop=self.loop) + + def receive_frame(self, frame): + """ + Make the protocol receive a frame. + + """ + writer = self.protocol.data_received + mask = not self.protocol.is_client + self.loop.call_soon(write_frame, frame, writer, mask) + + def receive_eof(self): + """ + Make the protocol receive the end of stream. + + WebSocketCommonProtocol.eof_received returns None — it is inherited + from StreamReaderProtocol. (Returning True wouldn't work on secure + connections anyway.) As a consequence, actual transports close + themselves after calling it. + + To emulate this behavior, this function closes the transport just + after calling the protocol's eof_received. Closing the transport has + the side-effect calling the protocol's connection_lost. + + """ + self.loop.call_soon(self.protocol.eof_received) + self.loop.call_soon(self.loop.call_soon, self.transport.close) + + def receive_eof_if_client(self): + """ + Like receive_eof, but only if this is the client side. + + Since the server is supposed to initiate the termination of the TCP + connection, this method helps making tests work for both sides. + + """ + if self.protocol.is_client: + self.receive_eof() + + def close_connection(self, code=1000, reason='close'): + """ + Close the connection with a standard closing handshake. + + This puts the connection in the CLOSED state. + + """ + close_frame_data = serialize_close(code, reason) + # Prepare the response to the closing handshake from the remote side. + self.receive_frame(Frame(True, OP_CLOSE, close_frame_data)) + self.receive_eof_if_client() + # Trigger the closing handshake from the local side and complete it. + self.loop.run_until_complete(self.protocol.close(code, reason)) + # Empty the outgoing data stream so we can make assertions later on. + self.assertOneFrameSent(True, OP_CLOSE, close_frame_data) + + def close_connection_partial(self, code=1000, reason='close'): + """ + Initiate a standard closing handshake but do not complete it. + + The main difference with `close_connection` is that the connection is + left in the CLOSING state until the event loop runs again. + + """ + close_frame_data = serialize_close(code, reason) + # Trigger the closing handshake from the local side. + self.ensure_future(self.protocol.close(code, reason)) + self.run_loop_once() + # Empty the outgoing data stream so we can make assertions later on. + self.assertOneFrameSent(True, OP_CLOSE, close_frame_data) + # Prepare the response to the closing handshake from the remote side. + self.receive_frame(Frame(True, OP_CLOSE, close_frame_data)) + self.receive_eof_if_client() + + def process_invalid_frames(self): + """ + Make the protocol fail quickly after simulating invalid data. + + To achieve this, this function triggers the protocol's eof_received, + which interrupts pending reads waiting for more data. It delays this + operation with call_later because the protocol must start processing + frames first. Otherwise it will see a closed connection and no data. + + """ + self.loop.call_later(MS, self.receive_eof) + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.recv()) + + def process_control_frames(self): + """ + Process control frames received by the protocol. + + To ensure that recv completes quickly, receive an additional dummy + frame, which recv() will drop. + + """ + self.receive_frame(Frame(True, OP_TEXT, b'')) + next_message = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(next_message, '') + + def last_sent_frame(self): + """ + Read the last frame sent to the transport. + + This method assumes that at most one frame was sent. It raises an + AssertionError otherwise. + + """ + stream = asyncio.StreamReader(loop=self.loop) + + for (data,), kw in self.transport.write.call_args_list: + stream.feed_data(data) + self.transport.write.call_args_list = [] + stream.feed_eof() + + if stream.at_eof(): + frame = None + else: + frame = self.loop.run_until_complete(read_frame( + stream.readexactly, self.protocol.is_client)) + + if not stream.at_eof(): # pragma: no cover + data = self.loop.run_until_complete(stream.read()) + raise AssertionError("Trailing data found: {!r}".format(data)) + + return frame + + def assertOneFrameSent(self, fin, opcode, data): + self.assertEqual(self.last_sent_frame(), Frame(fin, opcode, data)) + + def assertNoFrameSent(self): + self.assertIsNone(self.last_sent_frame()) + + def assertConnectionClosed(self, code, message): + # The following line guarantees that connection_lost was called. + self.assertEqual(self.protocol.state, CLOSED) + self.assertEqual(self.protocol.close_code, code) + self.assertEqual(self.protocol.close_reason, message) + + @contextlib.contextmanager + def assertCompletesWithin(self, min_time, max_time): + t0 = self.loop.time() + yield + t1 = self.loop.time() + dt = t1 - t0 + self.assertGreaterEqual( + dt, min_time, "Too fast: {} < {}".format(dt, min_time)) + self.assertLess( + dt, max_time, "Too slow: {} >= {}".format(dt, max_time)) + + # Test public attributes. + + def test_local_address(self): + get_extra_info = unittest.mock.Mock(return_value=('host', 4312)) + self.transport.get_extra_info = get_extra_info + # The connection isn't established yet. + self.assertEqual(self.protocol.local_address, None) + self.run_loop_once() + # The connection is established. + self.assertEqual(self.protocol.local_address, ('host', 4312)) + get_extra_info.assert_called_with('sockname', None) + + def test_remote_address(self): + get_extra_info = unittest.mock.Mock(return_value=('host', 4312)) + self.transport.get_extra_info = get_extra_info + # The connection isn't established yet. + self.assertEqual(self.protocol.remote_address, None) + self.run_loop_once() + # The connection is established. + self.assertEqual(self.protocol.remote_address, ('host', 4312)) + get_extra_info.assert_called_with('peername', None) + + def test_open(self): + self.assertTrue(self.protocol.open) + self.close_connection() + self.assertFalse(self.protocol.open) + + def test_state_name(self): + self.assertEqual(self.protocol.state_name, 'OPEN') + self.close_connection() + self.assertEqual(self.protocol.state_name, 'CLOSED') + + # Test the recv coroutine. + + def test_recv_text(self): + self.receive_frame(Frame(True, OP_TEXT, 'café'.encode('utf-8'))) + data = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(data, 'café') + + def test_recv_binary(self): + self.receive_frame(Frame(True, OP_BINARY, b'tea')) + data = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(data, b'tea') + + def test_recv_on_closing_connection(self): + self.close_connection_partial() + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.recv()) + + def test_recv_on_closed_connection(self): + self.close_connection() + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.recv()) + + def test_recv_protocol_error(self): + self.receive_frame(Frame(True, OP_CONT, 'café'.encode('utf-8'))) + self.process_invalid_frames() + self.assertConnectionClosed(1002, '') + + def test_recv_unicode_error(self): + self.receive_frame(Frame(True, OP_TEXT, 'café'.encode('latin-1'))) + self.process_invalid_frames() + self.assertConnectionClosed(1007, '') + + def test_recv_text_payload_too_big(self): + self.protocol.max_size = 1024 + self.receive_frame(Frame(True, OP_TEXT, 'café'.encode('utf-8') * 205)) + self.process_invalid_frames() + self.assertConnectionClosed(1009, '') + + def test_recv_binary_payload_too_big(self): + self.protocol.max_size = 1024 + self.receive_frame(Frame(True, OP_BINARY, b'tea' * 342)) + self.process_invalid_frames() + self.assertConnectionClosed(1009, '') + + def test_recv_text_no_max_size(self): + self.protocol.max_size = None # for test coverage + self.receive_frame(Frame(True, OP_TEXT, 'café'.encode('utf-8') * 205)) + data = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(data, 'café' * 205) + + def test_recv_binary_no_max_size(self): + self.protocol.max_size = None # for test coverage + self.receive_frame(Frame(True, OP_BINARY, b'tea' * 342)) + data = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(data, b'tea' * 342) + + def test_recv_other_error(self): + @asyncio.coroutine + def read_message(): + raise Exception("BOOM") + self.protocol.read_message = read_message + self.process_invalid_frames() + with self.assertRaises(Exception): + self.loop.run_until_complete(self.protocol.worker_task) + self.assertConnectionClosed(1011, '') + + def test_recv_cancelled(self): + recv = self.ensure_future(self.protocol.recv()) + self.loop.call_soon(recv.cancel) + with self.assertRaises(asyncio.CancelledError): + self.loop.run_until_complete(recv) + + # The next frame doesn't disappear in a vacuum (it used to). + self.receive_frame(Frame(True, OP_TEXT, 'café'.encode('utf-8'))) + data = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(data, 'café') + + # Test the send coroutine. + + def test_send_text(self): + self.loop.run_until_complete(self.protocol.send('café')) + self.assertOneFrameSent(True, OP_TEXT, 'café'.encode('utf-8')) + + def test_send_binary(self): + self.loop.run_until_complete(self.protocol.send(b'tea')) + self.assertOneFrameSent(True, OP_BINARY, b'tea') + + def test_send_type_error(self): + with self.assertRaises(TypeError): + self.loop.run_until_complete(self.protocol.send(42)) + self.assertNoFrameSent() + + def test_send_on_closing_connection(self): + self.close_connection_partial() + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.send('foobar')) + self.assertNoFrameSent() + + def test_send_on_closed_connection(self): + self.close_connection() + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.send('foobar')) + self.assertNoFrameSent() + + # Test the ping coroutine. + + def test_ping_default(self): + self.loop.run_until_complete(self.protocol.ping()) + # With our testing tools, it's more convenient to extract the expected + # ping data from the library's internals than from the frame sent. + ping_data = next(iter(self.protocol.pings)) + self.assertIsInstance(ping_data, bytes) + self.assertEqual(len(ping_data), 4) + self.assertOneFrameSent(True, OP_PING, ping_data) + + def test_ping_text(self): + self.loop.run_until_complete(self.protocol.ping('café')) + self.assertOneFrameSent(True, OP_PING, 'café'.encode('utf-8')) + + def test_ping_binary(self): + self.loop.run_until_complete(self.protocol.ping(b'tea')) + self.assertOneFrameSent(True, OP_PING, b'tea') + + def test_ping_type_error(self): + with self.assertRaises(TypeError): + self.loop.run_until_complete(self.protocol.ping(42)) + self.assertNoFrameSent() + + def test_ping_on_closing_connection(self): + self.close_connection_partial() + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.ping()) + self.assertNoFrameSent() + + def test_ping_on_closed_connection(self): + self.close_connection() + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.ping()) + self.assertNoFrameSent() + + # Test the pong coroutine. + + def test_pong_default(self): + self.loop.run_until_complete(self.protocol.pong()) + self.assertOneFrameSent(True, OP_PONG, b'') + + def test_pong_text(self): + self.loop.run_until_complete(self.protocol.pong('café')) + self.assertOneFrameSent(True, OP_PONG, 'café'.encode('utf-8')) + + def test_pong_binary(self): + self.loop.run_until_complete(self.protocol.pong(b'tea')) + self.assertOneFrameSent(True, OP_PONG, b'tea') + + def test_pong_type_error(self): + with self.assertRaises(TypeError): + self.loop.run_until_complete(self.protocol.pong(42)) + self.assertNoFrameSent() + + def test_pong_on_closing_connection(self): + self.close_connection_partial() + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.pong()) + self.assertNoFrameSent() + + def test_pong_on_closed_connection(self): + self.close_connection() + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.pong()) + self.assertNoFrameSent() + + # Test the protocol's logic for acknowledging pings with pongs. + + def test_answer_ping(self): + self.receive_frame(Frame(True, OP_PING, b'test')) + self.process_control_frames() + self.assertOneFrameSent(True, OP_PONG, b'test') + + def test_ignore_pong(self): + self.receive_frame(Frame(True, OP_PONG, b'test')) + self.process_control_frames() + self.assertNoFrameSent() + + def test_acknowledge_ping(self): + ping = self.loop.run_until_complete(self.protocol.ping()) + self.assertFalse(ping.done()) + ping_frame = self.last_sent_frame() + pong_frame = Frame(True, OP_PONG, ping_frame.data) + self.receive_frame(pong_frame) + self.process_control_frames() + self.assertTrue(ping.done()) + + def test_acknowledge_previous_pings(self): + pings = [( + self.loop.run_until_complete(self.protocol.ping()), + self.last_sent_frame(), + ) for i in range(3)] + # Unsolicited pong doesn't acknowledge pings + self.receive_frame(Frame(True, OP_PONG, b'')) + self.process_control_frames() + self.assertFalse(pings[0][0].done()) + self.assertFalse(pings[1][0].done()) + self.assertFalse(pings[2][0].done()) + # Pong acknowledges all previous pings + self.receive_frame(Frame(True, OP_PONG, pings[1][1].data)) + self.process_control_frames() + self.assertTrue(pings[0][0].done()) + self.assertTrue(pings[1][0].done()) + self.assertFalse(pings[2][0].done()) + + def test_cancel_ping(self): + ping = self.loop.run_until_complete(self.protocol.ping()) + ping_frame = self.last_sent_frame() + ping.cancel() + pong_frame = Frame(True, OP_PONG, ping_frame.data) + self.receive_frame(pong_frame) + self.process_control_frames() + self.assertTrue(ping.cancelled()) + + def test_duplicate_ping(self): + self.loop.run_until_complete(self.protocol.ping(b'foobar')) + self.assertOneFrameSent(True, OP_PING, b'foobar') + with self.assertRaises(ValueError): + self.loop.run_until_complete(self.protocol.ping(b'foobar')) + self.assertNoFrameSent() + + # Test the protocol's logic for rebuilding fragmented messages. + + def test_fragmented_text(self): + self.receive_frame(Frame(False, OP_TEXT, 'ca'.encode('utf-8'))) + self.receive_frame(Frame(True, OP_CONT, 'fé'.encode('utf-8'))) + data = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(data, 'café') + + def test_fragmented_binary(self): + self.receive_frame(Frame(False, OP_BINARY, b't')) + self.receive_frame(Frame(False, OP_CONT, b'e')) + self.receive_frame(Frame(True, OP_CONT, b'a')) + data = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(data, b'tea') + + def test_fragmented_text_payload_too_big(self): + self.protocol.max_size = 1024 + self.receive_frame(Frame(False, OP_TEXT, 'café'.encode('utf-8') * 100)) + self.receive_frame(Frame(True, OP_CONT, 'café'.encode('utf-8') * 105)) + self.process_invalid_frames() + self.assertConnectionClosed(1009, '') + + def test_fragmented_binary_payload_too_big(self): + self.protocol.max_size = 1024 + self.receive_frame(Frame(False, OP_BINARY, b'tea' * 171)) + self.receive_frame(Frame(True, OP_CONT, b'tea' * 171)) + self.process_invalid_frames() + self.assertConnectionClosed(1009, '') + + def test_fragmented_text_no_max_size(self): + self.protocol.max_size = None # for test coverage + self.receive_frame(Frame(False, OP_TEXT, 'café'.encode('utf-8') * 100)) + self.receive_frame(Frame(True, OP_CONT, 'café'.encode('utf-8') * 105)) + data = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(data, 'café' * 205) + + def test_fragmented_binary_no_max_size(self): + self.protocol.max_size = None # for test coverage + self.receive_frame(Frame(False, OP_BINARY, b'tea' * 171)) + self.receive_frame(Frame(True, OP_CONT, b'tea' * 171)) + data = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(data, b'tea' * 342) + + def test_control_frame_within_fragmented_text(self): + self.receive_frame(Frame(False, OP_TEXT, 'ca'.encode('utf-8'))) + self.receive_frame(Frame(True, OP_PING, b'')) + self.receive_frame(Frame(True, OP_CONT, 'fé'.encode('utf-8'))) + data = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(data, 'café') + self.assertOneFrameSent(True, OP_PONG, b'') + + def test_unterminated_fragmented_text(self): + self.receive_frame(Frame(False, OP_TEXT, 'ca'.encode('utf-8'))) + # Missing the second part of the fragmented frame. + self.receive_frame(Frame(True, OP_BINARY, b'tea')) + self.process_invalid_frames() + self.assertConnectionClosed(1002, '') + + def test_close_handshake_in_fragmented_text(self): + self.receive_frame(Frame(False, OP_TEXT, 'ca'.encode('utf-8'))) + self.receive_frame(Frame(True, OP_CLOSE, b'')) + self.process_invalid_frames() + self.assertConnectionClosed(1005, '') + + def test_connection_close_in_fragmented_text(self): + self.receive_frame(Frame(False, OP_TEXT, 'ca'.encode('utf-8'))) + self.process_invalid_frames() + self.assertConnectionClosed(1006, '') + + # Test miscellaneous code paths to ensure full coverage. + + def test_connection_lost(self): + # Test calling connection_lost without going through close_connection. + self.protocol.connection_lost(None) + + self.assertConnectionClosed(1006, '') + + def test_ensure_connection_before_opening_handshake(self): + self.protocol.state = CONNECTING + + with self.assertRaises(InvalidState): + self.loop.run_until_complete(self.protocol.ensure_open()) + + def test_legacy_recv(self): + # By default legacy_recv in disabled. + self.assertEqual(self.protocol.legacy_recv, False) + + self.close_connection() + + # Enable legacy_recv. + self.protocol.legacy_recv = True + + # Now recv() returns None instead of raising ConnectionClosed. + self.assertIsNone(self.loop.run_until_complete(self.protocol.recv())) + + def test_connection_closed_attributes(self): + self.close_connection() + + with self.assertRaises(ConnectionClosed) as context: + self.loop.run_until_complete(self.protocol.recv()) + + connection_closed = context.exception + self.assertEqual(connection_closed.code, 1000) + self.assertEqual(connection_closed.reason, 'close') + + # Test the protocol logic for closing the connection. + + def test_local_close(self): + # Emulate how the remote endpoint answers the closing handshake. + self.receive_frame(self.close_frame) + self.receive_eof_if_client() + + # Run the closing handshake. + self.loop.run_until_complete(self.protocol.close(reason='close')) + + self.assertConnectionClosed(1000, 'close') + self.assertOneFrameSent(*self.close_frame) + + # Closing the connection again is a no-op. + self.loop.run_until_complete(self.protocol.close(reason='oh noes!')) + + self.assertConnectionClosed(1000, 'close') + self.assertNoFrameSent() + + def test_remote_close(self): + # Emulate how the remote endpoint initiates the closing handshake. + self.receive_frame(self.close_frame) + self.receive_eof_if_client() + + # Wait for some data in order to process the handshake. + # After recv() raises ConnectionClosed, the connection is closed. + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.recv()) + + self.assertConnectionClosed(1000, 'close') + self.assertOneFrameSent(*self.close_frame) + + # Closing the connection again is a no-op. + self.loop.run_until_complete(self.protocol.close(reason='oh noes!')) + + self.assertConnectionClosed(1000, 'close') + self.assertNoFrameSent() + + def test_simultaneous_close(self): + self.receive_frame(self.remote_close) + self.receive_eof_if_client() + self.loop.run_until_complete(self.protocol.close(reason='local')) + + # The close code and reason are taken from the remote side because + # that's presumably more useful that the values from the local side. + self.assertConnectionClosed(1000, 'remote') + self.assertOneFrameSent(*self.local_close) + + def test_close_preserves_incoming_frames(self): + self.receive_frame(Frame(True, OP_TEXT, b'hello')) + self.receive_frame(self.close_frame) + self.receive_eof_if_client() + self.loop.run_until_complete(self.protocol.close(reason='close')) + + self.assertConnectionClosed(1000, 'close') + self.assertOneFrameSent(*self.close_frame) + + next_message = self.loop.run_until_complete(self.protocol.recv()) + self.assertEqual(next_message, 'hello') + + def test_close_protocol_error(self): + invalid_close_frame = Frame(True, OP_CLOSE, b'\x00') + self.receive_frame(invalid_close_frame) + self.receive_eof_if_client() + self.loop.run_until_complete(self.protocol.close(reason='close')) + + self.assertConnectionClosed(1002, '') + + def test_close_connection_lost(self): + self.receive_eof() + self.loop.run_until_complete(self.protocol.close(reason='close')) + + self.assertConnectionClosed(1006, '') + + def test_remote_close_race_with_failing_connection(self): + self.make_drain_slow() + + # Fail the connection while answering a close frame from the client. + self.loop.call_soon(self.receive_frame, self.remote_close) + self.loop.call_later( + MS, self.ensure_future, self.protocol.fail_connection()) + # The client expects the server to close the connection. + # Simulate it instead of waiting for the connection timeout. + self.loop.call_later(MS, self.receive_eof_if_client) + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(self.protocol.recv()) + + # The closing handshake was completed by fail_connection. + self.assertConnectionClosed(1011, '') + self.assertOneFrameSent(*self.remote_close) + + def test_local_close_during_recv(self): + recv = self.ensure_future(self.protocol.recv()) + + self.receive_frame(self.close_frame) + self.receive_eof_if_client() + + self.loop.run_until_complete(self.protocol.close(reason='close')) + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(recv) + + self.assertConnectionClosed(1000, 'close') + + # There is no test_remote_close_during_recv because it would be identical + # to test_remote_close. + + def test_remote_close_during_send(self): + self.make_drain_slow() + send = self.ensure_future(self.protocol.send('hello')) + + self.receive_frame(self.close_frame) + self.receive_eof() + + with self.assertRaises(ConnectionClosed): + self.loop.run_until_complete(send) + + self.assertConnectionClosed(1006, '') + + # There is no test_local_close_during_send because this cannot really + # happen, considering that writes are serialized. + + +class ServerTests(CommonTests, unittest.TestCase): + + def test_close_handshake_timeout(self): + # Timeout is expected in 10ms. + self.protocol.timeout = 10 * MS + # Check the timing within -1/+9ms for robustness. + with self.assertCompletesWithin(9 * MS, 19 * MS): + # Unlike previous tests, no close frame will be received in + # response. The server will stop waiting for the close frame and + # timeout. + self.loop.run_until_complete(self.protocol.close(reason='close')) + self.assertConnectionClosed(1006, '') + + +class ClientTests(CommonTests, unittest.TestCase): + + def setUp(self): + super().setUp() + self.protocol.is_client = True + + def test_close_handshake_timeout(self): + # Timeout is expected in 2 * 10 = 20ms. + self.protocol.timeout = 10 * MS + # Check the timing within -1/+9ms for robustness. + with self.assertCompletesWithin(19 * MS, 29 * MS): + # Unlike previous tests, no close frame will be received in + # response and the connection will not be closed. The client will + # stop waiting for the close frame and timeout, then stop waiting + # for the connection close and timeout again. + self.loop.run_until_complete(self.protocol.close(reason='close')) + self.assertConnectionClosed(1006, '') + + def test_eof_received_timeout(self): + # Timeout is expected in 10ms. + self.protocol.timeout = 10 * MS + # Check the timing within -1/+9ms for robustness. + with self.assertCompletesWithin(9 * MS, 19 * MS): + # Unlike previous tests, the close frame will be received in + # response but the connection will not be closed. The client will + # stop waiting for the connection close and timeout. + self.receive_frame(self.close_frame) + self.loop.run_until_complete(self.protocol.close(reason='close')) + + self.assertConnectionClosed(1000, 'close') diff --git a/venv/Lib/site-packages/websockets/extensions/__init__.py b/venv/Lib/site-packages/websockets/test_speedups.py similarity index 100% rename from venv/Lib/site-packages/websockets/extensions/__init__.py rename to venv/Lib/site-packages/websockets/test_speedups.py diff --git a/venv/Lib/site-packages/websockets/test_uri.py b/venv/Lib/site-packages/websockets/test_uri.py new file mode 100644 index 00000000..d1102ca6 --- /dev/null +++ b/venv/Lib/site-packages/websockets/test_uri.py @@ -0,0 +1,33 @@ +import unittest + +from .exceptions import InvalidURI +from .uri import * + + +VALID_URIS = [ + ('ws://localhost/', (False, 'localhost', 80, '/')), + ('wss://localhost/', (True, 'localhost', 443, '/')), + ('ws://localhost/path?query', (False, 'localhost', 80, '/path?query')), + ('WS://LOCALHOST/PATH?QUERY', (False, 'localhost', 80, '/PATH?QUERY')), +] + +INVALID_URIS = [ + 'http://localhost/', + 'https://localhost/', + 'ws://localhost/path#fragment', + 'ws://user:pass@localhost/', +] + + +class URITests(unittest.TestCase): + + def test_success(self): + for uri, parsed in VALID_URIS: + # wrap in `with self.subTest():` when dropping Python 3.3 + self.assertEqual(parse_uri(uri), parsed) + + def test_error(self): + for uri in INVALID_URIS: + # wrap in `with self.subTest():` when dropping Python 3.3 + with self.assertRaises(InvalidURI): + parse_uri(uri) diff --git a/venv/Lib/site-packages/websockets/test_utils.py b/venv/Lib/site-packages/websockets/test_utils.py new file mode 100644 index 00000000..8259b749 --- /dev/null +++ b/venv/Lib/site-packages/websockets/test_utils.py @@ -0,0 +1,50 @@ +import unittest + +from .utils import apply_mask as py_apply_mask + + +class UtilsTests(unittest.TestCase): + + @staticmethod + def apply_mask(*args, **kwargs): + return py_apply_mask(*args, **kwargs) + + def test_apply_mask(self): + for data_in, mask, data_out in [ + (b'', b'1234', b''), + (b'aBcDe', b'\x00\x00\x00\x00', b'aBcDe'), + (b'abcdABCD', b'1234', b'PPPPpppp'), + (b'abcdABCD' * 10, b'1234', b'PPPPpppp' * 10), + ]: + self.assertEqual(self.apply_mask(data_in, mask), data_out) + + def test_apply_mask_check_input_types(self): + for data_in, mask in [ + (None, None), + (b'abcd', None), + (None, b'abcd'), + ]: + with self.assertRaises(TypeError): + self.apply_mask(data_in, mask) + + def test_apply_mask_check_mask_length(self): + for data_in, mask in [ + (b'', b''), + (b'abcd', b'123'), + (b'', b'aBcDe'), + (b'12345678', b'12345678'), + ]: + with self.assertRaises(ValueError): + self.apply_mask(data_in, mask) + + +try: + from .speedups import apply_mask as c_apply_mask +except ImportError: # pragma: no cover + pass +else: + class SpeedupsTests(UtilsTests): + + @staticmethod + def apply_mask(*args, **kwargs): + return c_apply_mask(*args, **kwargs) diff --git a/venv/Lib/site-packages/websockets/uri.py b/venv/Lib/site-packages/websockets/uri.py index 6669e566..48c39c1a 100644 --- a/venv/Lib/site-packages/websockets/uri.py +++ b/venv/Lib/site-packages/websockets/uri.py @@ -1,81 +1,55 @@ """ -:mod:`websockets.uri` parses WebSocket URIs. - -See `section 3 of RFC 6455`_. +The :mod:`websockets.uri` module implements parsing of WebSocket URIs +according to `section 3 of RFC 6455`_. .. _section 3 of RFC 6455: http://tools.ietf.org/html/rfc6455#section-3 """ +import collections import urllib.parse -from typing import NamedTuple, Optional, Tuple from .exceptions import InvalidURI -__all__ = ["parse_uri", "WebSocketURI"] - +__all__ = ['parse_uri', 'WebSocketURI'] -# Consider converting to a dataclass when dropping support for Python < 3.7. +WebSocketURI = collections.namedtuple( + 'WebSocketURI', ('secure', 'host', 'port', 'resource_name')) +WebSocketURI.__doc__ = """WebSocket URI. +* ``secure`` is the secure flag +* ``host`` is the lower-case host +* ``port`` if the integer port, it's always provided even if it's the default +* ``resource_name`` is the resource name, that is, the path and optional query -class WebSocketURI(NamedTuple): - """ - WebSocket URI. +""" - :param bool secure: secure flag - :param str host: lower-case host - :param int port: port, always set even if it's the default - :param str resource_name: path and optional query - :param str user_info: ``(username, password)`` tuple when the URI contains - `User Information`_, else ``None``. - .. _User Information: https://tools.ietf.org/html/rfc3986#section-3.2.1 +def parse_uri(uri): """ + This function parses and validates a WebSocket URI. - secure: bool - host: str - port: int - resource_name: str - user_info: Optional[Tuple[str, str]] - - -# Work around https://bugs.python.org/issue19931 + If the URI is valid, it returns a :class:`WebSocketURI`. -WebSocketURI.secure.__doc__ = "" -WebSocketURI.host.__doc__ = "" -WebSocketURI.port.__doc__ = "" -WebSocketURI.resource_name.__doc__ = "" -WebSocketURI.user_info.__doc__ = "" + Otherwise it raises an :exc:`~websockets.exceptions.InvalidURI` exception. - -def parse_uri(uri: str) -> WebSocketURI: """ - Parse and validate a WebSocket URI. - - :raises ValueError: if ``uri`` isn't a valid WebSocket URI. - - """ - parsed = urllib.parse.urlparse(uri) + uri = urllib.parse.urlparse(uri) try: - assert parsed.scheme in ["ws", "wss"] - assert parsed.params == "" - assert parsed.fragment == "" - assert parsed.hostname is not None + assert uri.scheme in ('ws', 'wss') + assert uri.params == '' + assert uri.fragment == '' + assert uri.username is None + assert uri.password is None + assert uri.hostname is not None except AssertionError as exc: - raise InvalidURI(uri) from exc - - secure = parsed.scheme == "wss" - host = parsed.hostname - port = parsed.port or (443 if secure else 80) - resource_name = parsed.path or "/" - if parsed.query: - resource_name += "?" + parsed.query - user_info = None - if parsed.username is not None: - # urllib.parse.urlparse accepts URLs with a username but without a - # password. This doesn't make sense for HTTP Basic Auth credentials. - if parsed.password is None: - raise InvalidURI(uri) - user_info = (parsed.username, parsed.password) - return WebSocketURI(secure, host, port, resource_name, user_info) + raise InvalidURI() from exc + + secure = uri.scheme == 'wss' + host = uri.hostname + port = uri.port or (443 if secure else 80) + resource_name = uri.path or '/' + if uri.query: + resource_name += '?' + uri.query + return WebSocketURI(secure, host, port, resource_name) diff --git a/venv/Lib/site-packages/websockets/utils.py b/venv/Lib/site-packages/websockets/utils.py index 40ac8559..b4083dff 100644 --- a/venv/Lib/site-packages/websockets/utils.py +++ b/venv/Lib/site-packages/websockets/utils.py @@ -1,18 +1,14 @@ import itertools -__all__ = ["apply_mask"] +__all__ = ['apply_mask'] -def apply_mask(data: bytes, mask: bytes) -> bytes: +def apply_mask(data, mask): """ - Apply masking to the data of a WebSocket message. - - :param data: Data to mask - :param mask: 4-bytes mask + Apply masking to websocket message. """ if len(mask) != 4: raise ValueError("mask must contain 4 bytes") - return bytes(b ^ m for b, m in zip(data, itertools.cycle(mask))) diff --git a/venv/Lib/site-packages/websockets/version.py b/venv/Lib/site-packages/websockets/version.py index 7377332e..a0e73377 100644 --- a/venv/Lib/site-packages/websockets/version.py +++ b/venv/Lib/site-packages/websockets/version.py @@ -1 +1 @@ -version = "8.1" +version = '3.4' diff --git a/venv/Lib/site-packages/~ebsockets/__init__.py b/venv/Lib/site-packages/~ebsockets/__init__.py new file mode 100644 index 00000000..ea1d829a --- /dev/null +++ b/venv/Lib/site-packages/~ebsockets/__init__.py @@ -0,0 +1,55 @@ +# This relies on each of the submodules having an __all__ variable. + +from .auth import * # noqa +from .client import * # noqa +from .exceptions import * # noqa +from .protocol import * # noqa +from .server import * # noqa +from .typing import * # noqa +from .uri import * # noqa +from .version import version as __version__ # noqa + + +__all__ = [ + "AbortHandshake", + "basic_auth_protocol_factory", + "BasicAuthWebSocketServerProtocol", + "connect", + "ConnectionClosed", + "ConnectionClosedError", + "ConnectionClosedOK", + "Data", + "DuplicateParameter", + "ExtensionHeader", + "ExtensionParameter", + "InvalidHandshake", + "InvalidHeader", + "InvalidHeaderFormat", + "InvalidHeaderValue", + "InvalidMessage", + "InvalidOrigin", + "InvalidParameterName", + "InvalidParameterValue", + "InvalidState", + "InvalidStatusCode", + "InvalidUpgrade", + "InvalidURI", + "NegotiationError", + "Origin", + "parse_uri", + "PayloadTooBig", + "ProtocolError", + "RedirectHandshake", + "SecurityError", + "serve", + "Subprotocol", + "unix_connect", + "unix_serve", + "WebSocketClientProtocol", + "WebSocketCommonProtocol", + "WebSocketException", + "WebSocketProtocolError", + "WebSocketServer", + "WebSocketServerProtocol", + "WebSocketURI", +] diff --git a/venv/Lib/site-packages/websockets/__main__.py b/venv/Lib/site-packages/~ebsockets/__main__.py similarity index 100% rename from venv/Lib/site-packages/websockets/__main__.py rename to venv/Lib/site-packages/~ebsockets/__main__.py diff --git a/venv/Lib/site-packages/~ebsockets/speedups.cp36-win_amd64.pyd b/venv/Lib/site-packages/~ebsockets/speedups.cp36-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..6fca6ea044654ff9c272129393042196ab0375ce GIT binary patch literal 12288 zcmeHNeRLDom47mpZETDTv4|5wGNxk9N9+oVQWHawVw*fCa-x7CSsE(K_86_gA*4N(W3o112?dfs*|QW6ZMw6+ z`(|Wp0^L1lKmKSkJ~Q{e`|iE(zWeUG??Y}{|0tWn7|X@0>x}IOq{l73fBsWoVQl&> z2d1;9rXDNbZ}A>0Z|)4nrD!a&F&5~O+5+KlM3Gu$DV7LJ!LU?+&l;&K(k@pO7Z*BA z)$P1QI)~QqykicAapqZCp>P(GF4H7QS{M=O8At`pTGpv zP5L%=1l!}L_gX+CzJ+)vJZ|EP#ba%t3ExG55Z|qMCp>P!Cx;?nq%M$81z!~vEGd_1cz;4YU<0_9`6^$ zTOq_#4>$^VN^z9%)PoMmvknbNT)pU3FSrhAd6-(;Gl_gxW>|x)_AsJx=jk2w4!8Rm zOLE1pFj1IN_-sDabxdV!(0ULgvPC-r*6kT(qxSVew30493!oJu619KF2ZVPCzXVaO z0FpdyPe_8^0ifv!?Y>N6f#x&RNT_cx>X%ae8PpG2??Yo0TkdLo=Mk+Ky4>4!Ti@Nf zu4^w*E9z;UtYM0St3%pq(HEtRtFyU!MEeHp@v8rPfaDw17xk06^~(rE!;$I(4kuR? zM-5jWbZ|IJ@_c6C=(w-S?jtX`cV1Af_d~{YwlDKgt}8R*(}z;lRiJ1aFk0@NWAIc> za>Y+R0W-61T1nmhEP9oi^DWS|zXj^v`I2@I%yXS^?|e}U3PWv=52yn?Ylxd{@DE`8 z)q^~BzvNB1%Thj!8829OpBOZEqdKbo0mIgJB4Jx*&mfQ7*I7np()d0DKYP_d^%brj(@&a?4AF=x4%3_C<5?ocll1(G zs~0e#5>{;s<`2n3^u_UEs1d_3yyZW19X7ew7?b6U>yU2$2do5WSGWHS5Z&G>ibDsc z<}#Xt(x8)IB0#v#P-7}jBm=&{Cg2J zKA3BvmM_!Q;*Le2r@XmRmT2K>@n2_&5d0Imp<%NHtsd+$boLIp3&`FWc(UD50~5TCPOhTXs}7M{oQMb_MyW90b%=&X((Owj zrVl3doCkkI0pb75r$sy<4{HB}?m%I=%+=g^w2E+*7mQeW?T}LH%8YW`kBZ&Zj3s_o zZREjymXY_&9I8bO*?jHmm~JCCX!oIvEb&!?oLik4$=6gA_F2&C`~mb2CTSk{b2}2K zp)afJ5%3{RlF&?Tt5L|;J_lsv`~-Q;4~n)PACpM(SBdLJ^%6~H#Nx0vggJ&ucYX4Y z7AyFCBX8}5 z3o#AG=ki*vo~NKu&m=EdY>#{o`n0nc3XJC>OymmKN%>f0bv4x@enGTnR|-^`Qgq4Fk`juT1O4w1I1BJudUA{rj8NGuE-pxRh}Fi({_ z8f$;4l&N=4^Vasq3f0>Sru2JjGcjb2=jV^ShQUXcCzq5aw>sDt2rEQz=KwV5EZTlHkGr2*5w)R=ry5Fh`w&WMhA$@kpn<2GB%}N@DmO?FE8+d;B<=$4YAE5Ze*P@1 zzynPmL&248tabnv_an95OKl}G z;ROr4fED0IR3K*3#TSr#hYPUu^R)FH-~;23eDWqt;mLwr?F|FTG5wOZzAktvXRPJv zCmrrTg0c5}2JThQ7%R&6vGbt$q8>T6AUSU@_|ZnwsOyAh|8caZeG~OW(Cx?Uz|_Cj z1jpm2$r$wrGPZ7ij%uJ}c{Wq0&xu;WbU9nY=(I)^l&?uAArdWyUlOYOhNu!5-N#dX z)C}S_Er_1|yQo#Mp!Mwls^ySbsv&{>Ny}ip!v`g9z-G!dy8V?>1lpK|mO|*m7L=zO zMs1G`5YDO5In*dxbL;j(pvanq@1C8VDYt$XXAiD^%W)iT;=KpSTN}pnkl6c*^`EEb z+<613_(UDR$Skhba%^G{(JyI1GT~L894O$m{~G)46&nI5yJ9Z^UDFL+`5(|V=fBjY z&-0)ILT3qW%geHpAt`H^M=q@Gr$1(FeQkT{)&4>23n-GCdM~tjn(FJ-!}aP3Pwxde ztOPy17lUEB(bGE`R^(7a(eZlqY`tpz8YYvc_xGNJ(%DdSMm9dbC~I;4)( z7o8CCYul4*7_C3wWKr7g2L)(!fDmu*iB#ET$qfn+`;8<6yG=zX2pMs2;9 zn5~7ys5Te1!wWH+u!gYI+H)}EH??CAI$Vc@X=G8;7>r77&};|(ZK}|i1DT&f#$!A1 zdTBg7Xx%&4@YSGo4=}79qH1=04RPEQ_d=QFIPd?p#EXve)Y=kclM+YX^1MW~YE>YS z94Z*JwgEwmvUeLaDP`S&l5$;gNE)=>2^0~s+u z)_@1whk@rYzWTgsobdH|4~lPCe7nW>u=qYDzTXqy9pd|0@ePTu!M{u3G4WOK-Dep< zI~3hVj~;jj1|!+jW2BILet>F0&wfNc_cbD2(yS4)*o$)+EcB|Fsa{97n9$y|_1$vX zW*_G2ao1VhPWEDU6`-5RgT7DWlpEnx_cyVAv-h0EF<`T$i19H@_ z$LiHgBi0LVQ3lKI7eD1yUujeiH7)uj*AMglx2ACYd7i%MW$LZ%7B{xmIw``Q=E8y8)$-GYV(8q?EmNS=d=0o&8L^Q&{G@34U3!QVF05lHl# zyoz8leUlwJ0k6zCbP77dRWzuMVPEuk3Hnxh*tY!%ScY{HMV$Kj9!JTm))jbbtzQEv zvHr((JbhPM}GIn5B;gk%{9&k3P zZXCYh`z6=nzN>`y9a5;}`6KyQ>Cf6oKb^%>d1MD2$Wu0&R&*3LpUeK%&$-vqj)$vn z?QAk;-|*PGII4}4weoj#eP@$6#%&n>m+?9r_TS>FMMbv7QkH6VNSFv;`5m2T8=~r3 zj6hS1cJJG|{wNxEV)1}RA>lgITZ74;u|3wW_JdAA@ZWw8-)6ARsx?JS_#2b{lnK9W z!tEyPG-0y|-6lM^%+Pb%gcnViXV%X(Vb(yO*AOsLt4aT|S_+wz_s@>5F!8yOD3RvJX%458tp=@koYpNaZd;(EDoFRoj!%#r z+7wsURZeGH$3|SCqg+5Tb*phwt@991_hj07qHUW*YZQDtCesApqmyVp!MAHNP4InZ z60KSA?VU^$eEUENH+7ZbsR$b?eslR&;}%USjqmrnEU4Jwo5PNwoDspEi-! zZ19avq8WT+pzW}roo?gqJ^R~3m28yhHwYiuW%w3W!QG!^j6%tzxroL=n=l5@${5Xq zSFrS(e9(l)&6q^}GSoBacF?dDs%nknMjsCvqx=8tZvm{u97l2I@8}UcQM3g_-0wS_ z@EppZ?Yc}8b`t&1J!po_uop19GL_le^O=1~9Ye1OHdtawQwD~{#)EF=S;8?>pcxEeIO6@5Rz?3Vp3kN8FZ z^2hsUnVH9CDg|ujl6*F^y2wYq5jK1^$5~#O%LjG#)h~ezB6|`-jX%lD*4m zXxDl^T1O4f{9mo3voW@}CptRhn7=Vz7r~iwVvll>bh{gPCWMz#K3x+qc1r|`c z+x+VSp@fX8NQ|+4#Wjgm1sG#*LVHuBJrR=qbul@h$jCNlh$eSMVm<4E@)kddFc;a| zqsVdps#v7UFbz#oORU_qkQfaE?PMRZdt$Lbk6-SJDn0(V(Vq%alTjsJ3_k>R_~TjASlR?o?~Lsse%u^5i|zF4G9Mk@b1 zYqK2d3WnjGEQzJ2G{((BB(@5UgRQ=p9ETY5<=&f+V?91O)Rx1kpabR))Y{-E~8 zb~bkcwYd|c&<-LSCF+`j6 zTk}AVEA4)Y7Jo3@5%IUn7|2MEKLq8BeTsF-U2z%My1LbC?{02vYFNC)Y3N+aAQ4p1 z@h=)DC5JZ$ zW07zdxtlGS#1RS0-N=~=If$|4%pa3C!cxyb zZYaV(0r=Yl!UEA?WmlY1bS3I5@n0YchNCjHxN>o&+2w1c(~s!?PaeqLX&>7lo#;44 z_s?_#ZLGgJfFGBrborrmdEz5?V+ts8yA+TRk7ibu5aY;(n~@E(yc76ZDJ@opf}3P1 z()w9Q-zv?ks&+c#QU|6zX0o|GWL<&yCX&DB9wu<9D-l;jGXeZJ(Gp20G8+g)qoE#u zRsy$cRFOU& z(aQ-+LgI=eZ)}#O?DU8Wg+t~!2>YRJmFyptKb#&YDPe3eUOEfXo!EA~=W&WA_(Pm&-UodjAl(u>L0!=uLfCJv zsOXX76)QhgT(~?CkIP-HSj3?q9A8n9h=p&9w{^-`(<{4zZLvr^(xFtgMY?Va#Jj3C zFRs999}ae4x4mv+YozMqSzRbx#l{ac34@C9W-Yrrckkbw+0FN~?CIPCg4>|`cHfVh XM|bbqeR}t~-J`od)V}%)?EHTMI7)$% literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/websockets/typing.py b/venv/Lib/site-packages/~ebsockets/typing.py similarity index 100% rename from venv/Lib/site-packages/websockets/typing.py rename to venv/Lib/site-packages/~ebsockets/typing.py diff --git a/venv/Lib/site-packages/~ebsockets/uri.py b/venv/Lib/site-packages/~ebsockets/uri.py new file mode 100644 index 00000000..6669e566 --- /dev/null +++ b/venv/Lib/site-packages/~ebsockets/uri.py @@ -0,0 +1,81 @@ +""" +:mod:`websockets.uri` parses WebSocket URIs. + +See `section 3 of RFC 6455`_. + +.. _section 3 of RFC 6455: http://tools.ietf.org/html/rfc6455#section-3 + +""" + +import urllib.parse +from typing import NamedTuple, Optional, Tuple + +from .exceptions import InvalidURI + + +__all__ = ["parse_uri", "WebSocketURI"] + + +# Consider converting to a dataclass when dropping support for Python < 3.7. + + +class WebSocketURI(NamedTuple): + """ + WebSocket URI. + + :param bool secure: secure flag + :param str host: lower-case host + :param int port: port, always set even if it's the default + :param str resource_name: path and optional query + :param str user_info: ``(username, password)`` tuple when the URI contains + `User Information`_, else ``None``. + + .. _User Information: https://tools.ietf.org/html/rfc3986#section-3.2.1 + """ + + secure: bool + host: str + port: int + resource_name: str + user_info: Optional[Tuple[str, str]] + + +# Work around https://bugs.python.org/issue19931 + +WebSocketURI.secure.__doc__ = "" +WebSocketURI.host.__doc__ = "" +WebSocketURI.port.__doc__ = "" +WebSocketURI.resource_name.__doc__ = "" +WebSocketURI.user_info.__doc__ = "" + + +def parse_uri(uri: str) -> WebSocketURI: + """ + Parse and validate a WebSocket URI. + + :raises ValueError: if ``uri`` isn't a valid WebSocket URI. + + """ + parsed = urllib.parse.urlparse(uri) + try: + assert parsed.scheme in ["ws", "wss"] + assert parsed.params == "" + assert parsed.fragment == "" + assert parsed.hostname is not None + except AssertionError as exc: + raise InvalidURI(uri) from exc + + secure = parsed.scheme == "wss" + host = parsed.hostname + port = parsed.port or (443 if secure else 80) + resource_name = parsed.path or "/" + if parsed.query: + resource_name += "?" + parsed.query + user_info = None + if parsed.username is not None: + # urllib.parse.urlparse accepts URLs with a username but without a + # password. This doesn't make sense for HTTP Basic Auth credentials. + if parsed.password is None: + raise InvalidURI(uri) + user_info = (parsed.username, parsed.password) + return WebSocketURI(secure, host, port, resource_name, user_info) diff --git a/venv/Lib/site-packages/~ebsockets/utils.py b/venv/Lib/site-packages/~ebsockets/utils.py new file mode 100644 index 00000000..40ac8559 --- /dev/null +++ b/venv/Lib/site-packages/~ebsockets/utils.py @@ -0,0 +1,18 @@ +import itertools + + +__all__ = ["apply_mask"] + + +def apply_mask(data: bytes, mask: bytes) -> bytes: + """ + Apply masking to the data of a WebSocket message. + + :param data: Data to mask + :param mask: 4-bytes mask + + """ + if len(mask) != 4: + raise ValueError("mask must contain 4 bytes") + + return bytes(b ^ m for b, m in zip(data, itertools.cycle(mask))) diff --git a/venv/Lib/site-packages/~ebsockets/version.py b/venv/Lib/site-packages/~ebsockets/version.py new file mode 100644 index 00000000..7377332e --- /dev/null +++ b/venv/Lib/site-packages/~ebsockets/version.py @@ -0,0 +1 @@ +version = "8.1" diff --git a/venv/Lib/site-packages/~iohttp/__init__.py b/venv/Lib/site-packages/~iohttp/__init__.py new file mode 100644 index 00000000..58149e26 --- /dev/null +++ b/venv/Lib/site-packages/~iohttp/__init__.py @@ -0,0 +1,226 @@ +__version__ = '3.6.2' + +from typing import Tuple # noqa + +from . import hdrs as hdrs +from .client import BaseConnector as BaseConnector +from .client import ClientConnectionError as ClientConnectionError +from .client import ( + ClientConnectorCertificateError as ClientConnectorCertificateError, +) +from .client import ClientConnectorError as ClientConnectorError +from .client import ClientConnectorSSLError as ClientConnectorSSLError +from .client import ClientError as ClientError +from .client import ClientHttpProxyError as ClientHttpProxyError +from .client import ClientOSError as ClientOSError +from .client import ClientPayloadError as ClientPayloadError +from .client import ClientProxyConnectionError as ClientProxyConnectionError +from .client import ClientRequest as ClientRequest +from .client import ClientResponse as ClientResponse +from .client import ClientResponseError as ClientResponseError +from .client import ClientSession as ClientSession +from .client import ClientSSLError as ClientSSLError +from .client import ClientTimeout as ClientTimeout +from .client import ClientWebSocketResponse as ClientWebSocketResponse +from .client import ContentTypeError as ContentTypeError +from .client import Fingerprint as Fingerprint +from .client import InvalidURL as InvalidURL +from .client import NamedPipeConnector as NamedPipeConnector +from .client import RequestInfo as RequestInfo +from .client import ServerConnectionError as ServerConnectionError +from .client import ServerDisconnectedError as ServerDisconnectedError +from .client import ServerFingerprintMismatch as ServerFingerprintMismatch +from .client import ServerTimeoutError as ServerTimeoutError +from .client import TCPConnector as TCPConnector +from .client import TooManyRedirects as TooManyRedirects +from .client import UnixConnector as UnixConnector +from .client import WSServerHandshakeError as WSServerHandshakeError +from .client import request as request +from .cookiejar import CookieJar as CookieJar +from .cookiejar import DummyCookieJar as DummyCookieJar +from .formdata import FormData as FormData +from .helpers import BasicAuth as BasicAuth +from .helpers import ChainMapProxy as ChainMapProxy +from .http import HttpVersion as HttpVersion +from .http import HttpVersion10 as HttpVersion10 +from .http import HttpVersion11 as HttpVersion11 +from .http import WebSocketError as WebSocketError +from .http import WSCloseCode as WSCloseCode +from .http import WSMessage as WSMessage +from .http import WSMsgType as WSMsgType +from .multipart import ( + BadContentDispositionHeader as BadContentDispositionHeader, +) +from .multipart import BadContentDispositionParam as BadContentDispositionParam +from .multipart import BodyPartReader as BodyPartReader +from .multipart import MultipartReader as MultipartReader +from .multipart import MultipartWriter as MultipartWriter +from .multipart import ( + content_disposition_filename as content_disposition_filename, +) +from .multipart import parse_content_disposition as parse_content_disposition +from .payload import PAYLOAD_REGISTRY as PAYLOAD_REGISTRY +from .payload import AsyncIterablePayload as AsyncIterablePayload +from .payload import BufferedReaderPayload as BufferedReaderPayload +from .payload import BytesIOPayload as BytesIOPayload +from .payload import BytesPayload as BytesPayload +from .payload import IOBasePayload as IOBasePayload +from .payload import JsonPayload as JsonPayload +from .payload import Payload as Payload +from .payload import StringIOPayload as StringIOPayload +from .payload import StringPayload as StringPayload +from .payload import TextIOPayload as TextIOPayload +from .payload import get_payload as get_payload +from .payload import payload_type as payload_type +from .payload_streamer import streamer as streamer +from .resolver import AsyncResolver as AsyncResolver +from .resolver import DefaultResolver as DefaultResolver +from .resolver import ThreadedResolver as ThreadedResolver +from .signals import Signal as Signal +from .streams import EMPTY_PAYLOAD as EMPTY_PAYLOAD +from .streams import DataQueue as DataQueue +from .streams import EofStream as EofStream +from .streams import FlowControlDataQueue as FlowControlDataQueue +from .streams import StreamReader as StreamReader +from .tracing import TraceConfig as TraceConfig +from .tracing import ( + TraceConnectionCreateEndParams as TraceConnectionCreateEndParams, +) +from .tracing import ( + TraceConnectionCreateStartParams as TraceConnectionCreateStartParams, +) +from .tracing import ( + TraceConnectionQueuedEndParams as TraceConnectionQueuedEndParams, +) +from .tracing import ( + TraceConnectionQueuedStartParams as TraceConnectionQueuedStartParams, +) +from .tracing import ( + TraceConnectionReuseconnParams as TraceConnectionReuseconnParams, +) +from .tracing import TraceDnsCacheHitParams as TraceDnsCacheHitParams +from .tracing import TraceDnsCacheMissParams as TraceDnsCacheMissParams +from .tracing import ( + TraceDnsResolveHostEndParams as TraceDnsResolveHostEndParams, +) +from .tracing import ( + TraceDnsResolveHostStartParams as TraceDnsResolveHostStartParams, +) +from .tracing import TraceRequestChunkSentParams as TraceRequestChunkSentParams +from .tracing import TraceRequestEndParams as TraceRequestEndParams +from .tracing import TraceRequestExceptionParams as TraceRequestExceptionParams +from .tracing import TraceRequestRedirectParams as TraceRequestRedirectParams +from .tracing import TraceRequestStartParams as TraceRequestStartParams +from .tracing import ( + TraceResponseChunkReceivedParams as TraceResponseChunkReceivedParams, +) + +__all__ = ( + 'hdrs', + # client + 'BaseConnector', + 'ClientConnectionError', + 'ClientConnectorCertificateError', + 'ClientConnectorError', + 'ClientConnectorSSLError', + 'ClientError', + 'ClientHttpProxyError', + 'ClientOSError', + 'ClientPayloadError', + 'ClientProxyConnectionError', + 'ClientResponse', + 'ClientRequest', + 'ClientResponseError', + 'ClientSSLError', + 'ClientSession', + 'ClientTimeout', + 'ClientWebSocketResponse', + 'ContentTypeError', + 'Fingerprint', + 'InvalidURL', + 'RequestInfo', + 'ServerConnectionError', + 'ServerDisconnectedError', + 'ServerFingerprintMismatch', + 'ServerTimeoutError', + 'TCPConnector', + 'TooManyRedirects', + 'UnixConnector', + 'NamedPipeConnector', + 'WSServerHandshakeError', + 'request', + # cookiejar + 'CookieJar', + 'DummyCookieJar', + # formdata + 'FormData', + # helpers + 'BasicAuth', + 'ChainMapProxy', + # http + 'HttpVersion', + 'HttpVersion10', + 'HttpVersion11', + 'WSMsgType', + 'WSCloseCode', + 'WSMessage', + 'WebSocketError', + # multipart + 'BadContentDispositionHeader', + 'BadContentDispositionParam', + 'BodyPartReader', + 'MultipartReader', + 'MultipartWriter', + 'content_disposition_filename', + 'parse_content_disposition', + # payload + 'AsyncIterablePayload', + 'BufferedReaderPayload', + 'BytesIOPayload', + 'BytesPayload', + 'IOBasePayload', + 'JsonPayload', + 'PAYLOAD_REGISTRY', + 'Payload', + 'StringIOPayload', + 'StringPayload', + 'TextIOPayload', + 'get_payload', + 'payload_type', + # payload_streamer + 'streamer', + # resolver + 'AsyncResolver', + 'DefaultResolver', + 'ThreadedResolver', + # signals + 'Signal', + 'DataQueue', + 'EMPTY_PAYLOAD', + 'EofStream', + 'FlowControlDataQueue', + 'StreamReader', + # tracing + 'TraceConfig', + 'TraceConnectionCreateEndParams', + 'TraceConnectionCreateStartParams', + 'TraceConnectionQueuedEndParams', + 'TraceConnectionQueuedStartParams', + 'TraceConnectionReuseconnParams', + 'TraceDnsCacheHitParams', + 'TraceDnsCacheMissParams', + 'TraceDnsResolveHostEndParams', + 'TraceDnsResolveHostStartParams', + 'TraceRequestChunkSentParams', + 'TraceRequestEndParams', + 'TraceRequestExceptionParams', + 'TraceRequestRedirectParams', + 'TraceRequestStartParams', + 'TraceResponseChunkReceivedParams', +) # type: Tuple[str, ...] + +try: + from .worker import GunicornWebWorker, GunicornUVLoopWebWorker # noqa + __all__ += ('GunicornWebWorker', 'GunicornUVLoopWebWorker') +except ImportError: # pragma: no cover + pass diff --git a/venv/Lib/site-packages/aiohttp/_frozenlist.cp36-win_amd64.pyd b/venv/Lib/site-packages/~iohttp/_frozenlist.cp36-win_amd64.pyd similarity index 100% rename from venv/Lib/site-packages/aiohttp/_frozenlist.cp36-win_amd64.pyd rename to venv/Lib/site-packages/~iohttp/_frozenlist.cp36-win_amd64.pyd diff --git a/venv/Lib/site-packages/aiohttp/_frozenlist.pyx b/venv/Lib/site-packages/~iohttp/_frozenlist.pyx similarity index 100% rename from venv/Lib/site-packages/aiohttp/_frozenlist.pyx rename to venv/Lib/site-packages/~iohttp/_frozenlist.pyx diff --git a/venv/Lib/site-packages/aiohttp/_headers.pxi b/venv/Lib/site-packages/~iohttp/_headers.pxi similarity index 100% rename from venv/Lib/site-packages/aiohttp/_headers.pxi rename to venv/Lib/site-packages/~iohttp/_headers.pxi diff --git a/venv/Lib/site-packages/aiohttp/_helpers.c b/venv/Lib/site-packages/~iohttp/_helpers.c similarity index 100% rename from venv/Lib/site-packages/aiohttp/_helpers.c rename to venv/Lib/site-packages/~iohttp/_helpers.c diff --git a/venv/Lib/site-packages/aiohttp/_helpers.cp36-win_amd64.pyd b/venv/Lib/site-packages/~iohttp/_helpers.cp36-win_amd64.pyd similarity index 100% rename from venv/Lib/site-packages/aiohttp/_helpers.cp36-win_amd64.pyd rename to venv/Lib/site-packages/~iohttp/_helpers.cp36-win_amd64.pyd diff --git a/venv/Lib/site-packages/aiohttp/_helpers.pyi b/venv/Lib/site-packages/~iohttp/_helpers.pyi similarity index 100% rename from venv/Lib/site-packages/aiohttp/_helpers.pyi rename to venv/Lib/site-packages/~iohttp/_helpers.pyi diff --git a/venv/Lib/site-packages/aiohttp/_helpers.pyx b/venv/Lib/site-packages/~iohttp/_helpers.pyx similarity index 100% rename from venv/Lib/site-packages/aiohttp/_helpers.pyx rename to venv/Lib/site-packages/~iohttp/_helpers.pyx diff --git a/venv/Lib/site-packages/aiohttp/_http_parser.c b/venv/Lib/site-packages/~iohttp/_http_parser.c similarity index 100% rename from venv/Lib/site-packages/aiohttp/_http_parser.c rename to venv/Lib/site-packages/~iohttp/_http_parser.c diff --git a/venv/Lib/site-packages/aiohttp/_http_parser.cp36-win_amd64.pyd b/venv/Lib/site-packages/~iohttp/_http_parser.cp36-win_amd64.pyd similarity index 100% rename from venv/Lib/site-packages/aiohttp/_http_parser.cp36-win_amd64.pyd rename to venv/Lib/site-packages/~iohttp/_http_parser.cp36-win_amd64.pyd diff --git a/venv/Lib/site-packages/aiohttp/_http_parser.pyx b/venv/Lib/site-packages/~iohttp/_http_parser.pyx similarity index 100% rename from venv/Lib/site-packages/aiohttp/_http_parser.pyx rename to venv/Lib/site-packages/~iohttp/_http_parser.pyx diff --git a/venv/Lib/site-packages/aiohttp/_http_writer.c b/venv/Lib/site-packages/~iohttp/_http_writer.c similarity index 100% rename from venv/Lib/site-packages/aiohttp/_http_writer.c rename to venv/Lib/site-packages/~iohttp/_http_writer.c diff --git a/venv/Lib/site-packages/aiohttp/_http_writer.cp36-win_amd64.pyd b/venv/Lib/site-packages/~iohttp/_http_writer.cp36-win_amd64.pyd similarity index 100% rename from venv/Lib/site-packages/aiohttp/_http_writer.cp36-win_amd64.pyd rename to venv/Lib/site-packages/~iohttp/_http_writer.cp36-win_amd64.pyd diff --git a/venv/Lib/site-packages/aiohttp/_http_writer.pyx b/venv/Lib/site-packages/~iohttp/_http_writer.pyx similarity index 100% rename from venv/Lib/site-packages/aiohttp/_http_writer.pyx rename to venv/Lib/site-packages/~iohttp/_http_writer.pyx diff --git a/venv/Lib/site-packages/~iohttp/_websocket.c b/venv/Lib/site-packages/~iohttp/_websocket.c new file mode 100644 index 00000000..8082bfef --- /dev/null +++ b/venv/Lib/site-packages/~iohttp/_websocket.c @@ -0,0 +1,3562 @@ +/* Generated by Cython 0.29.13 */ + +#define PY_SSIZE_T_CLEAN +#include "Python.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) + #error Cython requires Python 2.6+ or Python 3.3+. +#else +#define CYTHON_ABI "0_29_13" +#define CYTHON_HEX_VERSION 0x001D0DF0 +#define CYTHON_FUTURE_DIVISION 1 +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#define __PYX_COMMA , +#ifndef HAVE_LONG_LONG + #if PY_VERSION_HEX >= 0x02070000 + #define HAVE_LONG_LONG + #endif +#endif +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #if PY_VERSION_HEX < 0x03050000 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#elif defined(PYSTON_VERSION) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #if PY_MAJOR_VERSION < 3 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if PY_VERSION_HEX < 0x030300F0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #ifndef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 1 + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) + #endif + #ifndef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) + #endif +#endif +#if !defined(CYTHON_FAST_PYCCALL) +#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #include "longintrepr.h" + #undef SHIFT + #undef BASE + #undef MASK + #ifdef SIZEOF_VOID_P + enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; + #endif +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#ifdef _MSC_VER + #ifndef _MSC_STDINT_H_ + #if _MSC_VER < 1300 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + #else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + #endif + #endif +#else + #include +#endif +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) && __cplusplus >= 201103L + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__ ) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif +#endif + +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #elif defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_INLINE inline + #else + #define CYTHON_INLINE + #endif +#endif + +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" +#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#else + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#endif + #define __Pyx_DefaultClassType PyType_Type +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #define __Pyx_PyCFunctionFast _PyCFunctionFast + #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords +#endif +#if CYTHON_FAST_PYCCALL +#define __Pyx_PyFastCFunction_Check(func)\ + ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) +#else +#define __Pyx_PyFastCFunction_Check(func) 0 +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 + #define PyMem_RawMalloc(n) PyMem_Malloc(n) + #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) + #define PyMem_RawFree(p) PyMem_Free(p) +#endif +#if CYTHON_COMPILING_IN_PYSTON + #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x03060000 + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#elif PY_VERSION_HEX >= 0x03000000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_Current +#endif +#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +#endif +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +#else +#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) +#else + #define CYTHON_PEP393_ENABLED 0 + #define PyUnicode_1BYTE_KIND 1 + #define PyUnicode_2BYTE_KIND 2 + #define PyUnicode_4BYTE_KIND 4 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyStringObject PyUnicodeObject + #define PyString_Type PyUnicode_Type + #define PyString_Check PyUnicode_Check + #define PyString_CheckExact PyUnicode_CheckExact + #define PyObject_Unicode PyObject_Str +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) +#endif +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) +#else + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyIntObject PyLongObject + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBoolObject PyLongObject +#endif +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t PyInt_AsLong +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) +#else + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) +#endif +#if CYTHON_USE_ASYNC_SLOTS + #if PY_VERSION_HEX >= 0x030500B1 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods + #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) + #else + #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #endif +#else + #define __Pyx_PyType_AsAsync(obj) NULL +#endif +#ifndef __Pyx_PyAsyncMethodsStruct + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + } __Pyx_PyAsyncMethodsStruct; +#endif + +#if defined(WIN32) || defined(MS_WINDOWS) + #define _USE_MATH_DEFINES +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) +#else +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} +#endif +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc +#else +#define __Pyx_truncl truncl +#endif + + +#define __PYX_ERR(f_index, lineno, Ln_error) \ +{ \ + __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \ +} + +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif +#endif + +#define __PYX_HAVE__aiohttp___websocket +#define __PYX_HAVE_API__aiohttp___websocket +/* Early includes */ +#include +#include +#include "pythread.h" +#include +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize +#endif +#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +#if CYTHON_ASSUME_SAFE_MACROS +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } + +static PyObject *__pyx_m = NULL; +static PyObject *__pyx_d; +static PyObject *__pyx_b; +static PyObject *__pyx_cython_runtime = NULL; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; + + +static const char *__pyx_f[] = { + "aiohttp\\_websocket.pyx", + "type.pxd", + "bool.pxd", + "complex.pxd", +}; + +/*--- Type declarations ---*/ + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* GetBuiltinName.proto */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name); + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* RaiseDoubleKeywords.proto */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywords.proto */ +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ + PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ + const char* function_name); + +/* PyCFunctionFastCall.proto */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); +#else +#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) +#endif + +/* PyFunctionFastCall.proto */ +#if CYTHON_FAST_PYCALL +#define __Pyx_PyFunction_FastCall(func, args, nargs)\ + __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); +#else +#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) +#endif +#define __Pyx_BUILD_ASSERT_EXPR(cond)\ + (sizeof(char [1 - 2*!(cond)]) - 1) +#ifndef Py_MEMBER_SIZE +#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) +#endif + static size_t __pyx_pyframe_localsplus_offset = 0; + #include "frameobject.h" + #define __Pxy_PyFrame_Initialize_Offsets()\ + ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ + (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) + #define __Pyx_PyFrame_GetLocalsplus(frame)\ + (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif + +/* PyObjectCall.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* TypeImport.proto */ +#ifndef __PYX_HAVE_RT_ImportType_proto +#define __PYX_HAVE_RT_ImportType_proto +enum __Pyx_ImportType_CheckSize { + __Pyx_ImportType_CheckSize_Error = 0, + __Pyx_ImportType_CheckSize_Warn = 1, + __Pyx_ImportType_CheckSize_Ignore = 2 +}; +static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); +#endif + +/* PyDictVersioning.proto */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __pyx_dict_cached_value;\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif + +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() PyErr_Occurred() +#endif + +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* CLineInTraceback.proto */ +#ifdef CYTHON_CLINE_IN_TRACEBACK +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#else +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#endif + +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) +#endif +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(void); + +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + + +/* Module declarations from 'cpython.version' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.type' */ +static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; + +/* Module declarations from 'libc.string' */ + +/* Module declarations from 'libc.stdio' */ + +/* Module declarations from 'cpython.object' */ + +/* Module declarations from 'cpython.ref' */ + +/* Module declarations from 'cpython.exc' */ + +/* Module declarations from 'cpython.module' */ + +/* Module declarations from 'cpython.mem' */ + +/* Module declarations from 'cpython.tuple' */ + +/* Module declarations from 'cpython.list' */ + +/* Module declarations from 'cpython.sequence' */ + +/* Module declarations from 'cpython.mapping' */ + +/* Module declarations from 'cpython.iterator' */ + +/* Module declarations from 'cpython.number' */ + +/* Module declarations from 'cpython.int' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.bool' */ +static PyTypeObject *__pyx_ptype_7cpython_4bool_bool = 0; + +/* Module declarations from 'cpython.long' */ + +/* Module declarations from 'cpython.float' */ + +/* Module declarations from '__builtin__' */ + +/* Module declarations from 'cpython.complex' */ +static PyTypeObject *__pyx_ptype_7cpython_7complex_complex = 0; + +/* Module declarations from 'cpython.string' */ + +/* Module declarations from 'cpython.unicode' */ + +/* Module declarations from 'cpython.dict' */ + +/* Module declarations from 'cpython.instance' */ + +/* Module declarations from 'cpython.function' */ + +/* Module declarations from 'cpython.method' */ + +/* Module declarations from 'cpython.weakref' */ + +/* Module declarations from 'cpython.getargs' */ + +/* Module declarations from 'cpython.pythread' */ + +/* Module declarations from 'cpython.pystate' */ + +/* Module declarations from 'cpython.cobject' */ + +/* Module declarations from 'cpython.oldbuffer' */ + +/* Module declarations from 'cpython.set' */ + +/* Module declarations from 'cpython.buffer' */ + +/* Module declarations from 'cpython.bytes' */ + +/* Module declarations from 'cpython.pycapsule' */ + +/* Module declarations from 'cpython' */ + +/* Module declarations from 'libc.stdint' */ + +/* Module declarations from 'aiohttp._websocket' */ +#define __Pyx_MODULE_NAME "aiohttp._websocket" +extern int __pyx_module_is_main_aiohttp___websocket; +int __pyx_module_is_main_aiohttp___websocket = 0; + +/* Implementation of 'aiohttp._websocket' */ +static PyObject *__pyx_builtin_range; +static const char __pyx_k_i[] = "i"; +static const char __pyx_k_data[] = "data"; +static const char __pyx_k_main[] = "__main__"; +static const char __pyx_k_mask[] = "mask"; +static const char __pyx_k_name[] = "__name__"; +static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_range[] = "range"; +static const char __pyx_k_in_buf[] = "in_buf"; +static const char __pyx_k_data_len[] = "data_len"; +static const char __pyx_k_mask_buf[] = "mask_buf"; +static const char __pyx_k_uint32_msk[] = "uint32_msk"; +static const char __pyx_k_uint64_msk[] = "uint64_msk"; +static const char __pyx_k_aiohttp__websocket[] = "aiohttp._websocket"; +static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; +static const char __pyx_k_websocket_mask_cython[] = "_websocket_mask_cython"; +static const char __pyx_k_aiohttp__websocket_pyx[] = "aiohttp\\_websocket.pyx"; +static PyObject *__pyx_n_s_aiohttp__websocket; +static PyObject *__pyx_kp_s_aiohttp__websocket_pyx; +static PyObject *__pyx_n_s_cline_in_traceback; +static PyObject *__pyx_n_s_data; +static PyObject *__pyx_n_s_data_len; +static PyObject *__pyx_n_s_i; +static PyObject *__pyx_n_s_in_buf; +static PyObject *__pyx_n_s_main; +static PyObject *__pyx_n_s_mask; +static PyObject *__pyx_n_s_mask_buf; +static PyObject *__pyx_n_s_name; +static PyObject *__pyx_n_s_range; +static PyObject *__pyx_n_s_test; +static PyObject *__pyx_n_s_uint32_msk; +static PyObject *__pyx_n_s_uint64_msk; +static PyObject *__pyx_n_s_websocket_mask_cython; +static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_mask, PyObject *__pyx_v_data); /* proto */ +static PyObject *__pyx_tuple_; +static PyObject *__pyx_codeobj__2; +/* Late includes */ + +/* "aiohttp/_websocket.pyx":9 + * from libc.stdint cimport uint32_t, uint64_t, uintmax_t + * + * def _websocket_mask_cython(object mask, object data): # <<<<<<<<<<<<<< + * """Note, this function mutates its `data` argument + * """ + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_7aiohttp_10_websocket_1_websocket_mask_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_7aiohttp_10_websocket__websocket_mask_cython[] = "Note, this function mutates its `data` argument\n "; +static PyMethodDef __pyx_mdef_7aiohttp_10_websocket_1_websocket_mask_cython = {"_websocket_mask_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_7aiohttp_10_websocket_1_websocket_mask_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7aiohttp_10_websocket__websocket_mask_cython}; +static PyObject *__pyx_pw_7aiohttp_10_websocket_1_websocket_mask_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_mask = 0; + PyObject *__pyx_v_data = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("_websocket_mask_cython (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_mask,&__pyx_n_s_data,0}; + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mask)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_websocket_mask_cython", 1, 2, 2, 1); __PYX_ERR(0, 9, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_websocket_mask_cython") < 0)) __PYX_ERR(0, 9, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + } + __pyx_v_mask = values[0]; + __pyx_v_data = values[1]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_websocket_mask_cython", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 9, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("aiohttp._websocket._websocket_mask_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(__pyx_self, __pyx_v_mask, __pyx_v_data); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_mask, PyObject *__pyx_v_data) { + Py_ssize_t __pyx_v_data_len; + Py_ssize_t __pyx_v_i; + unsigned char *__pyx_v_in_buf; + unsigned char const *__pyx_v_mask_buf; + uint32_t __pyx_v_uint32_msk; + uint64_t __pyx_v_uint64_msk; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + Py_ssize_t __pyx_t_1; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + char *__pyx_t_5; + uint64_t *__pyx_t_6; + long __pyx_t_7; + uint32_t *__pyx_t_8; + Py_ssize_t __pyx_t_9; + Py_ssize_t __pyx_t_10; + Py_ssize_t __pyx_t_11; + __Pyx_RefNannySetupContext("_websocket_mask_cython", 0); + __Pyx_INCREF(__pyx_v_mask); + __Pyx_INCREF(__pyx_v_data); + + /* "aiohttp/_websocket.pyx":20 + * uint64_t uint64_msk + * + * assert len(mask) == 4 # <<<<<<<<<<<<<< + * + * if not isinstance(mask, bytes): + */ + #ifndef CYTHON_WITHOUT_ASSERTIONS + if (unlikely(!Py_OptimizeFlag)) { + __pyx_t_1 = PyObject_Length(__pyx_v_mask); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 20, __pyx_L1_error) + if (unlikely(!((__pyx_t_1 == 4) != 0))) { + PyErr_SetNone(PyExc_AssertionError); + __PYX_ERR(0, 20, __pyx_L1_error) + } + } + #endif + + /* "aiohttp/_websocket.pyx":22 + * assert len(mask) == 4 + * + * if not isinstance(mask, bytes): # <<<<<<<<<<<<<< + * mask = bytes(mask) + * + */ + __pyx_t_2 = PyBytes_Check(__pyx_v_mask); + __pyx_t_3 = ((!(__pyx_t_2 != 0)) != 0); + if (__pyx_t_3) { + + /* "aiohttp/_websocket.pyx":23 + * + * if not isinstance(mask, bytes): + * mask = bytes(mask) # <<<<<<<<<<<<<< + * + * if isinstance(data, bytearray): + */ + __pyx_t_4 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyBytes_Type)), __pyx_v_mask); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 23, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_mask, __pyx_t_4); + __pyx_t_4 = 0; + + /* "aiohttp/_websocket.pyx":22 + * assert len(mask) == 4 + * + * if not isinstance(mask, bytes): # <<<<<<<<<<<<<< + * mask = bytes(mask) + * + */ + } + + /* "aiohttp/_websocket.pyx":25 + * mask = bytes(mask) + * + * if isinstance(data, bytearray): # <<<<<<<<<<<<<< + * data = data + * else: + */ + __pyx_t_3 = PyByteArray_Check(__pyx_v_data); + __pyx_t_2 = (__pyx_t_3 != 0); + if (__pyx_t_2) { + + /* "aiohttp/_websocket.pyx":26 + * + * if isinstance(data, bytearray): + * data = data # <<<<<<<<<<<<<< + * else: + * data = bytearray(data) + */ + __pyx_t_4 = __pyx_v_data; + __Pyx_INCREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_data, __pyx_t_4); + __pyx_t_4 = 0; + + /* "aiohttp/_websocket.pyx":25 + * mask = bytes(mask) + * + * if isinstance(data, bytearray): # <<<<<<<<<<<<<< + * data = data + * else: + */ + goto __pyx_L4; + } + + /* "aiohttp/_websocket.pyx":28 + * data = data + * else: + * data = bytearray(data) # <<<<<<<<<<<<<< + * + * data_len = len(data) + */ + /*else*/ { + __pyx_t_4 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyByteArray_Type)), __pyx_v_data); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 28, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF_SET(__pyx_v_data, __pyx_t_4); + __pyx_t_4 = 0; + } + __pyx_L4:; + + /* "aiohttp/_websocket.pyx":30 + * data = bytearray(data) + * + * data_len = len(data) # <<<<<<<<<<<<<< + * in_buf = PyByteArray_AsString(data) + * mask_buf = PyBytes_AsString(mask) + */ + __pyx_t_1 = PyObject_Length(__pyx_v_data); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 30, __pyx_L1_error) + __pyx_v_data_len = __pyx_t_1; + + /* "aiohttp/_websocket.pyx":31 + * + * data_len = len(data) + * in_buf = PyByteArray_AsString(data) # <<<<<<<<<<<<<< + * mask_buf = PyBytes_AsString(mask) + * uint32_msk = (mask_buf)[0] + */ + if (!(likely(PyByteArray_CheckExact(__pyx_v_data))||((__pyx_v_data) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytearray", Py_TYPE(__pyx_v_data)->tp_name), 0))) __PYX_ERR(0, 31, __pyx_L1_error) + __pyx_t_5 = PyByteArray_AsString(((PyObject*)__pyx_v_data)); if (unlikely(__pyx_t_5 == ((char *)NULL))) __PYX_ERR(0, 31, __pyx_L1_error) + __pyx_v_in_buf = ((unsigned char *)__pyx_t_5); + + /* "aiohttp/_websocket.pyx":32 + * data_len = len(data) + * in_buf = PyByteArray_AsString(data) + * mask_buf = PyBytes_AsString(mask) # <<<<<<<<<<<<<< + * uint32_msk = (mask_buf)[0] + * + */ + __pyx_t_5 = PyBytes_AsString(__pyx_v_mask); if (unlikely(__pyx_t_5 == ((char *)NULL))) __PYX_ERR(0, 32, __pyx_L1_error) + __pyx_v_mask_buf = ((unsigned char const *)__pyx_t_5); + + /* "aiohttp/_websocket.pyx":33 + * in_buf = PyByteArray_AsString(data) + * mask_buf = PyBytes_AsString(mask) + * uint32_msk = (mask_buf)[0] # <<<<<<<<<<<<<< + * + * # TODO: align in_data ptr to achieve even faster speeds + */ + __pyx_v_uint32_msk = (((uint32_t *)__pyx_v_mask_buf)[0]); + + /* "aiohttp/_websocket.pyx":38 + * # does it need in python ?! malloc() always aligns to sizeof(long) bytes + * + * if sizeof(size_t) >= 8: # <<<<<<<<<<<<<< + * uint64_msk = uint32_msk + * uint64_msk = (uint64_msk << 32) | uint32_msk + */ + __pyx_t_2 = (((sizeof(size_t)) >= 8) != 0); + if (__pyx_t_2) { + + /* "aiohttp/_websocket.pyx":39 + * + * if sizeof(size_t) >= 8: + * uint64_msk = uint32_msk # <<<<<<<<<<<<<< + * uint64_msk = (uint64_msk << 32) | uint32_msk + * + */ + __pyx_v_uint64_msk = __pyx_v_uint32_msk; + + /* "aiohttp/_websocket.pyx":40 + * if sizeof(size_t) >= 8: + * uint64_msk = uint32_msk + * uint64_msk = (uint64_msk << 32) | uint32_msk # <<<<<<<<<<<<<< + * + * while data_len >= 8: + */ + __pyx_v_uint64_msk = ((__pyx_v_uint64_msk << 32) | __pyx_v_uint32_msk); + + /* "aiohttp/_websocket.pyx":42 + * uint64_msk = (uint64_msk << 32) | uint32_msk + * + * while data_len >= 8: # <<<<<<<<<<<<<< + * (in_buf)[0] ^= uint64_msk + * in_buf += 8 + */ + while (1) { + __pyx_t_2 = ((__pyx_v_data_len >= 8) != 0); + if (!__pyx_t_2) break; + + /* "aiohttp/_websocket.pyx":43 + * + * while data_len >= 8: + * (in_buf)[0] ^= uint64_msk # <<<<<<<<<<<<<< + * in_buf += 8 + * data_len -= 8 + */ + __pyx_t_6 = ((uint64_t *)__pyx_v_in_buf); + __pyx_t_7 = 0; + (__pyx_t_6[__pyx_t_7]) = ((__pyx_t_6[__pyx_t_7]) ^ __pyx_v_uint64_msk); + + /* "aiohttp/_websocket.pyx":44 + * while data_len >= 8: + * (in_buf)[0] ^= uint64_msk + * in_buf += 8 # <<<<<<<<<<<<<< + * data_len -= 8 + * + */ + __pyx_v_in_buf = (__pyx_v_in_buf + 8); + + /* "aiohttp/_websocket.pyx":45 + * (in_buf)[0] ^= uint64_msk + * in_buf += 8 + * data_len -= 8 # <<<<<<<<<<<<<< + * + * + */ + __pyx_v_data_len = (__pyx_v_data_len - 8); + } + + /* "aiohttp/_websocket.pyx":38 + * # does it need in python ?! malloc() always aligns to sizeof(long) bytes + * + * if sizeof(size_t) >= 8: # <<<<<<<<<<<<<< + * uint64_msk = uint32_msk + * uint64_msk = (uint64_msk << 32) | uint32_msk + */ + } + + /* "aiohttp/_websocket.pyx":48 + * + * + * while data_len >= 4: # <<<<<<<<<<<<<< + * (in_buf)[0] ^= uint32_msk + * in_buf += 4 + */ + while (1) { + __pyx_t_2 = ((__pyx_v_data_len >= 4) != 0); + if (!__pyx_t_2) break; + + /* "aiohttp/_websocket.pyx":49 + * + * while data_len >= 4: + * (in_buf)[0] ^= uint32_msk # <<<<<<<<<<<<<< + * in_buf += 4 + * data_len -= 4 + */ + __pyx_t_8 = ((uint32_t *)__pyx_v_in_buf); + __pyx_t_7 = 0; + (__pyx_t_8[__pyx_t_7]) = ((__pyx_t_8[__pyx_t_7]) ^ __pyx_v_uint32_msk); + + /* "aiohttp/_websocket.pyx":50 + * while data_len >= 4: + * (in_buf)[0] ^= uint32_msk + * in_buf += 4 # <<<<<<<<<<<<<< + * data_len -= 4 + * + */ + __pyx_v_in_buf = (__pyx_v_in_buf + 4); + + /* "aiohttp/_websocket.pyx":51 + * (in_buf)[0] ^= uint32_msk + * in_buf += 4 + * data_len -= 4 # <<<<<<<<<<<<<< + * + * for i in range(0, data_len): + */ + __pyx_v_data_len = (__pyx_v_data_len - 4); + } + + /* "aiohttp/_websocket.pyx":53 + * data_len -= 4 + * + * for i in range(0, data_len): # <<<<<<<<<<<<<< + * in_buf[i] ^= mask_buf[i] + */ + __pyx_t_1 = __pyx_v_data_len; + __pyx_t_9 = __pyx_t_1; + for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) { + __pyx_v_i = __pyx_t_10; + + /* "aiohttp/_websocket.pyx":54 + * + * for i in range(0, data_len): + * in_buf[i] ^= mask_buf[i] # <<<<<<<<<<<<<< + */ + __pyx_t_11 = __pyx_v_i; + (__pyx_v_in_buf[__pyx_t_11]) = ((__pyx_v_in_buf[__pyx_t_11]) ^ (__pyx_v_mask_buf[__pyx_v_i])); + } + + /* "aiohttp/_websocket.pyx":9 + * from libc.stdint cimport uint32_t, uint64_t, uintmax_t + * + * def _websocket_mask_cython(object mask, object data): # <<<<<<<<<<<<<< + * """Note, this function mutates its `data` argument + * """ + */ + + /* function exit code */ + __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_4); + __Pyx_AddTraceback("aiohttp._websocket._websocket_mask_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_mask); + __Pyx_XDECREF(__pyx_v_data); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; + +#if PY_MAJOR_VERSION >= 3 +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec__websocket(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec__websocket}, + {0, NULL} +}; +#endif + +static struct PyModuleDef __pyx_moduledef = { + PyModuleDef_HEAD_INIT, + "_websocket", + 0, /* m_doc */ + #if CYTHON_PEP489_MULTI_PHASE_INIT + 0, /* m_size */ + #else + -1, /* m_size */ + #endif + __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else + NULL, /* m_reload */ + #endif + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_n_s_aiohttp__websocket, __pyx_k_aiohttp__websocket, sizeof(__pyx_k_aiohttp__websocket), 0, 0, 1, 1}, + {&__pyx_kp_s_aiohttp__websocket_pyx, __pyx_k_aiohttp__websocket_pyx, sizeof(__pyx_k_aiohttp__websocket_pyx), 0, 0, 1, 0}, + {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_data, __pyx_k_data, sizeof(__pyx_k_data), 0, 0, 1, 1}, + {&__pyx_n_s_data_len, __pyx_k_data_len, sizeof(__pyx_k_data_len), 0, 0, 1, 1}, + {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1}, + {&__pyx_n_s_in_buf, __pyx_k_in_buf, sizeof(__pyx_k_in_buf), 0, 0, 1, 1}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_n_s_mask, __pyx_k_mask, sizeof(__pyx_k_mask), 0, 0, 1, 1}, + {&__pyx_n_s_mask_buf, __pyx_k_mask_buf, sizeof(__pyx_k_mask_buf), 0, 0, 1, 1}, + {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, + {&__pyx_n_s_uint32_msk, __pyx_k_uint32_msk, sizeof(__pyx_k_uint32_msk), 0, 0, 1, 1}, + {&__pyx_n_s_uint64_msk, __pyx_k_uint64_msk, sizeof(__pyx_k_uint64_msk), 0, 0, 1, 1}, + {&__pyx_n_s_websocket_mask_cython, __pyx_k_websocket_mask_cython, sizeof(__pyx_k_websocket_mask_cython), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 53, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "aiohttp/_websocket.pyx":9 + * from libc.stdint cimport uint32_t, uint64_t, uintmax_t + * + * def _websocket_mask_cython(object mask, object data): # <<<<<<<<<<<<<< + * """Note, this function mutates its `data` argument + * """ + */ + __pyx_tuple_ = PyTuple_Pack(8, __pyx_n_s_mask, __pyx_n_s_data, __pyx_n_s_data_len, __pyx_n_s_i, __pyx_n_s_in_buf, __pyx_n_s_mask_buf, __pyx_n_s_uint32_msk, __pyx_n_s_uint64_msk); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple_); + __Pyx_GIVEREF(__pyx_tuple_); + __pyx_codeobj__2 = (PyObject*)__Pyx_PyCode_New(2, 0, 8, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple_, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_aiohttp__websocket_pyx, __pyx_n_s_websocket_mask_cython, 9, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__2)) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ + +static int __Pyx_modinit_global_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_import_code(void) { + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", + #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 + sizeof(PyTypeObject), + #else + sizeof(PyHeapTypeObject), + #endif + __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(1, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_4bool_bool = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "bool", sizeof(PyBoolObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_4bool_bool) __PYX_ERR(2, 8, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 15, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_ptype_7cpython_7complex_complex = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "complex", sizeof(PyComplexObject), __Pyx_ImportType_CheckSize_Warn); + if (!__pyx_ptype_7cpython_7complex_complex) __PYX_ERR(3, 15, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_variable_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + + +#if PY_MAJOR_VERSION < 3 +#ifdef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC void +#else +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#endif +#else +#ifdef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC PyObject * +#else +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#endif +#endif + + +#if PY_MAJOR_VERSION < 3 +__Pyx_PyMODINIT_FUNC init_websocket(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC init_websocket(void) +#else +__Pyx_PyMODINIT_FUNC PyInit__websocket(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit__websocket(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + #if PY_VERSION_HEX >= 0x030700A1 + static PY_INT64_T main_interpreter_id = -1; + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return (unlikely(current_id == -1)) ? -1 : 0; + } else if (unlikely(main_interpreter_id != current_id)) + #else + static PyInterpreterState *main_interpreter = NULL; + PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; + if (!main_interpreter) { + main_interpreter = current_interpreter; + } else if (unlikely(main_interpreter != current_interpreter)) + #endif + { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + if (allow_none || value != Py_None) { + result = PyDict_SetItemString(moddict, to_name, value); + } + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + if (__Pyx_check_single_interpreter()) + return NULL; + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec__websocket(PyObject *__pyx_pyinit_module) +#endif +#endif +{ + PyObject *__pyx_t_1 = NULL; + __Pyx_RefNannyDeclarations + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module '_websocket' has already been imported. Re-initialisation is not supported."); + return -1; + } + #elif PY_MAJOR_VERSION >= 3 + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + #if CYTHON_REFNANNY +__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); +if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); +} +#endif + __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit__websocket(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pxy_PyFrame_Initialize_Offsets + __Pxy_PyFrame_Initialize_Offsets(); + #endif + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_AsyncGen_USED + if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + /*--- Library function declarations ---*/ + /*--- Threads initialization code ---*/ + #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + #ifdef WITH_THREAD /* Python build with threading support? */ + PyEval_InitThreads(); + #endif + #endif + /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_m = __pyx_pyinit_module; + Py_INCREF(__pyx_m); + #else + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4("_websocket", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_b); + __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_cython_runtime); + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + if (__pyx_module_is_main_aiohttp___websocket) { + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "aiohttp._websocket")) { + if (unlikely(PyDict_SetItemString(modules, "aiohttp._websocket", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #endif + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins() < 0) goto __pyx_L1_error; + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants() < 0) goto __pyx_L1_error; + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(); + (void)__Pyx_modinit_variable_export_code(); + (void)__Pyx_modinit_function_export_code(); + (void)__Pyx_modinit_type_init_code(); + if (unlikely(__Pyx_modinit_type_import_code() != 0)) goto __pyx_L1_error; + (void)__Pyx_modinit_variable_import_code(); + (void)__Pyx_modinit_function_import_code(); + /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + + /* "aiohttp/_websocket.pyx":9 + * from libc.stdint cimport uint32_t, uint64_t, uintmax_t + * + * def _websocket_mask_cython(object mask, object data): # <<<<<<<<<<<<<< + * """Note, this function mutates its `data` argument + * """ + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7aiohttp_10_websocket_1_websocket_mask_cython, NULL, __pyx_n_s_aiohttp__websocket); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_websocket_mask_cython, __pyx_t_1) < 0) __PYX_ERR(0, 9, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "aiohttp/_websocket.pyx":1 + * from cpython cimport PyBytes_AsString # <<<<<<<<<<<<<< + * + * #from cpython cimport PyByteArray_AsString # cython still not exports that + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + if (__pyx_m) { + if (__pyx_d) { + __Pyx_AddTraceback("init aiohttp._websocket", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_CLEAR(__pyx_m); + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init aiohttp._websocket"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #elif PY_MAJOR_VERSION >= 3 + return __pyx_m; + #else + return; + #endif +} + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule(modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, "RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* PyObjectGetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* GetBuiltinName */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name) { + PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); + if (unlikely(!result)) { + PyErr_Format(PyExc_NameError, +#if PY_MAJOR_VERSION >= 3 + "name '%U' is not defined", name); +#else + "name '%.200s' is not defined", PyString_AS_STRING(name)); +#endif + } + return result; +} + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* RaiseDoubleKeywords */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AsString(kw_name)); + #endif +} + +/* ParseKeywords */ +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + continue; + } + name = first_kw_arg; + #if PY_MAJOR_VERSION < 3 + if (likely(PyString_CheckExact(key)) || likely(PyString_Check(key))) { + while (*name) { + if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) + && _PyString_Eq(**name, key)) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + if ((**argname == key) || ( + (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) + && _PyString_Eq(**argname, key))) { + goto arg_passed_twice; + } + argname++; + } + } + } else + #endif + if (likely(PyUnicode_Check(key))) { + while (*name) { + int cmp = (**name == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 : + #endif + PyUnicode_Compare(**name, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + int cmp = (**argname == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 : + #endif + PyUnicode_Compare(**argname, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + argname++; + } + } + } else + goto invalid_keyword_type; + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + +/* PyCFunctionFastCall */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { + PyCFunctionObject *func = (PyCFunctionObject*)func_obj; + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + int flags = PyCFunction_GET_FLAGS(func); + assert(PyCFunction_Check(func)); + assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); + assert(nargs >= 0); + assert(nargs == 0 || args != NULL); + /* _PyCFunction_FastCallDict() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller loses its exception */ + assert(!PyErr_Occurred()); + if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { + return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); + } else { + return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); + } +} +#endif + +/* PyFunctionFastCall */ +#if CYTHON_FAST_PYCALL +static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, + PyObject *globals) { + PyFrameObject *f; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject **fastlocals; + Py_ssize_t i; + PyObject *result; + assert(globals != NULL); + /* XXX Perhaps we should create a specialized + PyFrame_New() that doesn't take locals, but does + take builtins without sanity checking them. + */ + assert(tstate != NULL); + f = PyFrame_New(tstate, co, globals, NULL); + if (f == NULL) { + return NULL; + } + fastlocals = __Pyx_PyFrame_GetLocalsplus(f); + for (i = 0; i < na; i++) { + Py_INCREF(*args); + fastlocals[i] = *args++; + } + result = PyEval_EvalFrameEx(f,0); + ++tstate->recursion_depth; + Py_DECREF(f); + --tstate->recursion_depth; + return result; +} +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { + PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); + PyObject *globals = PyFunction_GET_GLOBALS(func); + PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *closure; +#if PY_MAJOR_VERSION >= 3 + PyObject *kwdefs; +#endif + PyObject *kwtuple, **k; + PyObject **d; + Py_ssize_t nd; + Py_ssize_t nk; + PyObject *result; + assert(kwargs == NULL || PyDict_Check(kwargs)); + nk = kwargs ? PyDict_Size(kwargs) : 0; + if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { + return NULL; + } + if ( +#if PY_MAJOR_VERSION >= 3 + co->co_kwonlyargcount == 0 && +#endif + likely(kwargs == NULL || nk == 0) && + co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { + if (argdefs == NULL && co->co_argcount == nargs) { + result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); + goto done; + } + else if (nargs == 0 && argdefs != NULL + && co->co_argcount == Py_SIZE(argdefs)) { + /* function called with no arguments, but all parameters have + a default value: use default values as arguments .*/ + args = &PyTuple_GET_ITEM(argdefs, 0); + result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); + goto done; + } + } + if (kwargs != NULL) { + Py_ssize_t pos, i; + kwtuple = PyTuple_New(2 * nk); + if (kwtuple == NULL) { + result = NULL; + goto done; + } + k = &PyTuple_GET_ITEM(kwtuple, 0); + pos = i = 0; + while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { + Py_INCREF(k[i]); + Py_INCREF(k[i+1]); + i += 2; + } + nk = i / 2; + } + else { + kwtuple = NULL; + k = NULL; + } + closure = PyFunction_GET_CLOSURE(func); +#if PY_MAJOR_VERSION >= 3 + kwdefs = PyFunction_GET_KW_DEFAULTS(func); +#endif + if (argdefs != NULL) { + d = &PyTuple_GET_ITEM(argdefs, 0); + nd = Py_SIZE(argdefs); + } + else { + d = NULL; + nd = 0; + } +#if PY_MAJOR_VERSION >= 3 + result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, kwdefs, closure); +#else + result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, closure); +#endif + Py_XDECREF(kwtuple); +done: + Py_LeaveRecursiveCall(); + return result; +} +#endif +#endif + +/* PyObjectCall */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = func->ob_type->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallMethO */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = PyCFunction_GET_FUNCTION(func); + self = PyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallOneArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_New(1); + if (unlikely(!args)) return NULL; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, &arg, 1); + } +#endif + if (likely(PyCFunction_Check(func))) { + if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { + return __Pyx_PyObject_CallMethO(func, arg); +#if CYTHON_FAST_PYCCALL + } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { + return __Pyx_PyCFunction_FastCall(func, &arg, 1); +#endif + } + } + return __Pyx__PyObject_CallOneArg(func, arg); +} +#else +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_Pack(1, arg); + if (unlikely(!args)) return NULL; + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +#endif + +/* TypeImport */ +#ifndef __PYX_HAVE_RT_ImportType +#define __PYX_HAVE_RT_ImportType +static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, + size_t size, enum __Pyx_ImportType_CheckSize check_size) +{ + PyObject *result = 0; + char warning[200]; + Py_ssize_t basicsize; +#ifdef Py_LIMITED_API + PyObject *py_basicsize; +#endif + result = PyObject_GetAttrString(module, class_name); + if (!result) + goto bad; + if (!PyType_Check(result)) { + PyErr_Format(PyExc_TypeError, + "%.200s.%.200s is not a type object", + module_name, class_name); + goto bad; + } +#ifndef Py_LIMITED_API + basicsize = ((PyTypeObject *)result)->tp_basicsize; +#else + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) + goto bad; + basicsize = PyLong_AsSsize_t(py_basicsize); + Py_DECREF(py_basicsize); + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; +#endif + if ((size_t)basicsize < size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + goto bad; + } + else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { + PyOS_snprintf(warning, sizeof(warning), + "%s.%s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", + module_name, class_name, size, basicsize); + if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; + } + return (PyTypeObject *)result; +bad: + Py_XDECREF(result); + return NULL; +} +#endif + +/* PyDictVersioning */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* PyErrFetchRestore */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} +#endif + +/* CLineInTraceback */ +#ifndef CYTHON_CLINE_IN_TRACEBACK +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { + PyObject *use_cline; + PyObject *ptype, *pvalue, *ptraceback; +#if CYTHON_COMPILING_IN_CPYTHON + PyObject **cython_runtime_dict; +#endif + if (unlikely(!__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); +#if CYTHON_COMPILING_IN_CPYTHON + cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, *cython_runtime_dict, + __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) + } else +#endif + { + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); + if (use_cline_obj) { + use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; + Py_DECREF(use_cline_obj); + } else { + PyErr_Clear(); + use_cline = NULL; + } + } + if (!use_cline) { + c_line = 0; + PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + } + else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache */ +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; + } + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; + } + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); +} + +/* AddTraceback */ +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyObject *py_srcfile = 0; + PyObject *py_funcname = 0; + #if PY_MAJOR_VERSION < 3 + py_srcfile = PyString_FromString(filename); + #else + py_srcfile = PyUnicode_FromString(filename); + #endif + if (!py_srcfile) goto bad; + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + #else + py_funcname = PyUnicode_FromString(funcname); + #endif + } + if (!py_funcname) goto bad; + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + Py_DECREF(py_funcname); + return py_code; +bad: + Py_XDECREF(py_srcfile); + Py_XDECREF(py_funcname); + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) goto bad; + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { + const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + +/* CIntFromPyVerify */ +#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* CIntFromPy */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { + const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; +} + +/* CIntFromPy */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { + const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; + } + } else { + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; +} + +/* FastTypeChecks */ +#if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = a->tp_base; + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(a, b); +} +#if PY_MAJOR_VERSION == 2 +static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { + PyObject *exception, *value, *tb; + int res; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&exception, &value, &tb); + res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + if (!res) { + res = PyObject_IsSubclass(err, exc_type2); + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + } + __Pyx_ErrRestore(exception, value, tb); + return res; +} +#else +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; + if (!res) { + res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } + return res; +} +#endif +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; ip) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + if (PyObject_Hash(*t->p) == -1) + return -1; + ++t; + } + return 0; +} + +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +#if !CYTHON_PEP393_ENABLED +static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +} +#else +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +} +#endif +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + Py_TYPE(result)->tp_name)) { + Py_DECREF(result); + return NULL; + } + return result; + } +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + type_name, type_name, Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS + PyNumberMethods *m; +#endif + const char *name = NULL; + PyObject *res = NULL; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x) || PyLong_Check(x))) +#else + if (likely(PyLong_Check(x))) +#endif + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS + m = Py_TYPE(x)->tp_as_number; + #if PY_MAJOR_VERSION < 3 + if (m && m->nb_int) { + name = "int"; + res = m->nb_int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = m->nb_long(x); + } + #else + if (likely(m && m->nb_int)) { + name = "int"; + res = m->nb_int(x); + } + #endif +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Int(x); + } +#endif + if (likely(res)) { +#if PY_MAJOR_VERSION < 3 + if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { +#else + if (unlikely(!PyLong_CheckExact(res))) { +#endif + return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(b); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); +} +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); +} + + +#endif /* Py_PYTHON_H */ diff --git a/venv/Lib/site-packages/aiohttp/_websocket.cp36-win_amd64.pyd b/venv/Lib/site-packages/~iohttp/_websocket.cp36-win_amd64.pyd similarity index 100% rename from venv/Lib/site-packages/aiohttp/_websocket.cp36-win_amd64.pyd rename to venv/Lib/site-packages/~iohttp/_websocket.cp36-win_amd64.pyd diff --git a/venv/Lib/site-packages/~iohttp/_websocket.pyx b/venv/Lib/site-packages/~iohttp/_websocket.pyx new file mode 100644 index 00000000..e4d992a7 --- /dev/null +++ b/venv/Lib/site-packages/~iohttp/_websocket.pyx @@ -0,0 +1,54 @@ +from cpython cimport PyBytes_AsString + +#from cpython cimport PyByteArray_AsString # cython still not exports that +cdef extern from "Python.h": + char* PyByteArray_AsString(bytearray ba) except NULL + +from libc.stdint cimport uint32_t, uint64_t, uintmax_t + +def _websocket_mask_cython(object mask, object data): + """Note, this function mutates its `data` argument + """ + cdef: + Py_ssize_t data_len, i + # bit operations on signed integers are implementation-specific + unsigned char * in_buf + const unsigned char * mask_buf + uint32_t uint32_msk + uint64_t uint64_msk + + assert len(mask) == 4 + + if not isinstance(mask, bytes): + mask = bytes(mask) + + if isinstance(data, bytearray): + data = data + else: + data = bytearray(data) + + data_len = len(data) + in_buf = PyByteArray_AsString(data) + mask_buf = PyBytes_AsString(mask) + uint32_msk = (mask_buf)[0] + + # TODO: align in_data ptr to achieve even faster speeds + # does it need in python ?! malloc() always aligns to sizeof(long) bytes + + if sizeof(size_t) >= 8: + uint64_msk = uint32_msk + uint64_msk = (uint64_msk << 32) | uint32_msk + + while data_len >= 8: + (in_buf)[0] ^= uint64_msk + in_buf += 8 + data_len -= 8 + + + while data_len >= 4: + (in_buf)[0] ^= uint32_msk + in_buf += 4 + data_len -= 4 + + for i in range(0, data_len): + in_buf[i] ^= mask_buf[i]