python-engineio 4.12.2__tar.gz → 4.13.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. {python_engineio-4.12.2/src/python_engineio.egg-info → python_engineio-4.13.0}/PKG-INFO +4 -2
  2. {python_engineio-4.12.2 → python_engineio-4.13.0}/docs/client.rst +7 -3
  3. {python_engineio-4.12.2 → python_engineio-4.13.0}/docs/server.rst +7 -3
  4. {python_engineio-4.12.2 → python_engineio-4.13.0}/pyproject.toml +11 -4
  5. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_client.py +14 -6
  6. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_drivers/aiohttp.py +9 -16
  7. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_drivers/asgi.py +3 -3
  8. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_drivers/tornado.py +2 -1
  9. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_server.py +6 -5
  10. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/base_server.py +4 -1
  11. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/client.py +15 -3
  12. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/server.py +2 -2
  13. {python_engineio-4.12.2 → python_engineio-4.13.0/src/python_engineio.egg-info}/PKG-INFO +4 -2
  14. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/python_engineio.egg-info/requires.txt +3 -0
  15. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/async/test_aiohttp.py +19 -6
  16. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/async/test_client.py +64 -66
  17. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/async/test_server.py +26 -2
  18. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/common/test_client.py +44 -49
  19. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/common/test_server.py +25 -2
  20. {python_engineio-4.12.2 → python_engineio-4.13.0}/tox.ini +2 -3
  21. {python_engineio-4.12.2 → python_engineio-4.13.0}/LICENSE +0 -0
  22. {python_engineio-4.12.2 → python_engineio-4.13.0}/MANIFEST.in +0 -0
  23. {python_engineio-4.12.2 → python_engineio-4.13.0}/README.md +0 -0
  24. {python_engineio-4.12.2 → python_engineio-4.13.0}/docs/Makefile +0 -0
  25. {python_engineio-4.12.2 → python_engineio-4.13.0}/docs/_static/README.md +0 -0
  26. {python_engineio-4.12.2 → python_engineio-4.13.0}/docs/api.rst +0 -0
  27. {python_engineio-4.12.2 → python_engineio-4.13.0}/docs/conf.py +0 -0
  28. {python_engineio-4.12.2 → python_engineio-4.13.0}/docs/index.rst +0 -0
  29. {python_engineio-4.12.2 → python_engineio-4.13.0}/docs/intro.rst +0 -0
  30. {python_engineio-4.12.2 → python_engineio-4.13.0}/docs/make.bat +0 -0
  31. {python_engineio-4.12.2 → python_engineio-4.13.0}/setup.cfg +0 -0
  32. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/__init__.py +0 -0
  33. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_drivers/__init__.py +0 -0
  34. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_drivers/_websocket_wsgi.py +0 -0
  35. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_drivers/eventlet.py +0 -0
  36. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_drivers/gevent.py +0 -0
  37. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_drivers/gevent_uwsgi.py +0 -0
  38. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_drivers/sanic.py +0 -0
  39. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_drivers/threading.py +0 -0
  40. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/async_socket.py +0 -0
  41. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/base_client.py +0 -0
  42. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/base_socket.py +0 -0
  43. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/exceptions.py +0 -0
  44. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/json.py +0 -0
  45. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/middleware.py +0 -0
  46. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/packet.py +0 -0
  47. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/payload.py +0 -0
  48. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/socket.py +0 -0
  49. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/engineio/static_files.py +0 -0
  50. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/python_engineio.egg-info/SOURCES.txt +0 -0
  51. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/python_engineio.egg-info/dependency_links.txt +0 -0
  52. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/python_engineio.egg-info/not-zip-safe +0 -0
  53. {python_engineio-4.12.2 → python_engineio-4.13.0}/src/python_engineio.egg-info/top_level.txt +0 -0
  54. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/__init__.py +0 -0
  55. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/async/__init__.py +0 -0
  56. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/async/index.html +0 -0
  57. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/async/test_asgi.py +0 -0
  58. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/async/test_sanic.py +0 -0
  59. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/async/test_socket.py +0 -0
  60. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/async/test_tornado.py +0 -0
  61. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/common/__init__.py +0 -0
  62. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/common/index.html +0 -0
  63. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/common/test_middleware.py +0 -0
  64. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/common/test_packet.py +0 -0
  65. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/common/test_payload.py +0 -0
  66. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/common/test_socket.py +0 -0
  67. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/performance/README.md +0 -0
  68. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/performance/binary_b64_packet.py +0 -0
  69. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/performance/binary_packet.py +0 -0
  70. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/performance/json_packet.py +0 -0
  71. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/performance/payload.py +0 -0
  72. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/performance/run.sh +0 -0
  73. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/performance/server_receive.py +0 -0
  74. {python_engineio-4.12.2 → python_engineio-4.13.0}/tests/performance/text_packet.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-engineio
3
- Version: 4.12.2
3
+ Version: 4.13.0
4
4
  Summary: Engine.IO server and client for Python
5
5
  Author-email: Miguel Grinberg <miguel.grinberg@gmail.com>
6
6
  License: MIT
@@ -10,7 +10,7 @@ Classifier: Environment :: Web Environment
10
10
  Classifier: Intended Audience :: Developers
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Operating System :: OS Independent
13
- Requires-Python: >=3.6
13
+ Requires-Python: >=3.8
14
14
  Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: simple-websocket>=0.10.0
@@ -19,6 +19,8 @@ Requires-Dist: requests>=2.21.0; extra == "client"
19
19
  Requires-Dist: websocket-client>=0.54.0; extra == "client"
20
20
  Provides-Extra: asyncio-client
21
21
  Requires-Dist: aiohttp>=3.4; extra == "asyncio-client"
22
+ Provides-Extra: dev
23
+ Requires-Dist: tox; extra == "dev"
22
24
  Provides-Extra: docs
23
25
  Requires-Dist: sphinx; extra == "docs"
24
26
  Dynamic: license-file
@@ -199,9 +199,13 @@ terminal::
199
199
  # asyncio
200
200
  eio = engineio.AsyncClient(logger=True)
201
201
 
202
- The ``logger`` argument can be set to ``True`` to output logs to ``stderr``, or
203
- to an object compatible with Python's ``logging`` package where the logs should
204
- be emitted to. A value of ``False`` disables logging.
202
+ The ``logger`` argument controls logging behavior:
203
+
204
+ * ``True``: Enables log output to ``stderr`` at the ``INFO`` level.
205
+ * ``False``: Enables log output to ``stderr`` at the ``ERROR`` level. This is
206
+ the default.
207
+ * A ``logging.Logger`` instance: Uses the provided logger without additional
208
+ configuration.
205
209
 
206
210
  Logging can help identify the cause of connection problems, unexpected
207
211
  disconnections and other issues.
@@ -350,9 +350,13 @@ terminal::
350
350
  # asyncio
351
351
  eio = engineio.AsyncServer(logger=True)
352
352
 
353
- The ``logger`` argument can be set to ``True`` to output logs to ``stderr``, or
354
- to an object compatible with Python's ``logging`` package where the logs should
355
- be emitted to. A value of ``False`` disables logging.
353
+ The ``logger`` argument controls logging behavior:
354
+
355
+ * ``True``: Enables log output to ``stderr`` at the ``INFO`` level.
356
+ * ``False``: Enables log output to ``stderr`` at the ``ERROR`` level. This is
357
+ the default.
358
+ * A ``logging.Logger`` instance: Uses the provided logger without additional
359
+ configuration.
356
360
 
357
361
  Logging can help identify the cause of connection problems, 400 responses,
358
362
  bad performance and other issues.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "python-engineio"
3
- version = "4.12.2"
3
+ version = "4.13.0"
4
4
  license = {text = "MIT"}
5
5
  authors = [{name = "Miguel Grinberg", email = "miguel.grinberg@gmail.com"}]
6
6
  description = "Engine.IO server and client for Python"
@@ -10,7 +10,7 @@ classifiers = [
10
10
  "Programming Language :: Python :: 3",
11
11
  "Operating System :: OS Independent",
12
12
  ]
13
- requires-python = ">=3.6"
13
+ requires-python = ">=3.8"
14
14
  dependencies = ["simple-websocket >= 0.10.0"]
15
15
 
16
16
  [project.readme]
@@ -26,8 +26,15 @@ client = [
26
26
  "requests >= 2.21.0",
27
27
  "websocket-client >= 0.54.0",
28
28
  ]
29
- asyncio_client = ["aiohttp >= 3.4"]
30
- docs = ["sphinx"]
29
+ asyncio_client = [
30
+ "aiohttp >= 3.4"
31
+ ]
32
+ dev = [
33
+ "tox",
34
+ ]
35
+ docs = [
36
+ "sphinx",
37
+ ]
31
38
 
32
39
  [tool.setuptools]
33
40
  zip-safe = false
@@ -1,4 +1,6 @@
1
1
  import asyncio
2
+ from http.cookies import SimpleCookie
3
+ import inspect
2
4
  import signal
3
5
  import ssl
4
6
  import threading
@@ -214,6 +216,12 @@ class AsyncClient(base_client.BaseClient):
214
216
 
215
217
  async def _reset(self):
216
218
  super()._reset()
219
+ while True: # pragma: no cover
220
+ try:
221
+ self.queue.get_nowait()
222
+ self.queue.task_done()
223
+ except self.queue_empty:
224
+ break
217
225
  if not self.external_http: # pragma: no cover
218
226
  if self.http and not self.http.closed:
219
227
  await self.http.close()
@@ -313,16 +321,16 @@ class AsyncClient(base_client.BaseClient):
313
321
 
314
322
  # extract any new cookies passed in a header so that they can also be
315
323
  # sent the the WebSocket route
316
- cookies = {}
317
324
  for header, value in headers.items():
318
325
  if header.lower() == 'cookie':
319
- cookies = dict(
320
- [cookie.split('=', 1) for cookie in value.split('; ')])
326
+ ck = SimpleCookie(headers[header])
327
+ self.http.cookie_jar.update_cookies(
328
+ {k: m.value for k, m in ck.items()})
321
329
  del headers[header]
322
330
  break
323
- self.http.cookie_jar.update_cookies(cookies)
324
331
 
325
- extra_options = {'timeout': self.request_timeout}
332
+ extra_options = {
333
+ 'timeout': aiohttp.ClientWSTimeout(ws_close=self.request_timeout)}
326
334
  if not self.ssl_verify:
327
335
  ssl_context = ssl.create_default_context()
328
336
  ssl_context.check_hostname = False
@@ -462,7 +470,7 @@ class AsyncClient(base_client.BaseClient):
462
470
  run_async = kwargs.pop('run_async', False)
463
471
  ret = None
464
472
  if event in self.handlers:
465
- if asyncio.iscoroutinefunction(self.handlers[event]) is True:
473
+ if inspect.iscoroutinefunction(self.handlers[event]) is True:
466
474
  if run_async:
467
475
  task = self.start_background_task(self.handlers[event],
468
476
  *args)
@@ -1,6 +1,5 @@
1
- import asyncio
1
+ import inspect
2
2
  import sys
3
- from urllib.parse import urlsplit
4
3
 
5
4
  from aiohttp.web import Response, WebSocketResponse
6
5
 
@@ -22,12 +21,8 @@ def translate_request(request):
22
21
  """This function takes the arguments passed to the request handler and
23
22
  uses them to generate a WSGI compatible environ dictionary.
24
23
  """
25
- message = request._message
26
- payload = request._payload
27
-
28
- uri_parts = urlsplit(message.path)
29
24
  environ = {
30
- 'wsgi.input': payload,
25
+ 'wsgi.input': request.content,
31
26
  'wsgi.errors': sys.stderr,
32
27
  'wsgi.version': (1, 0),
33
28
  'wsgi.async': True,
@@ -35,10 +30,10 @@ def translate_request(request):
35
30
  'wsgi.multiprocess': False,
36
31
  'wsgi.run_once': False,
37
32
  'SERVER_SOFTWARE': 'aiohttp',
38
- 'REQUEST_METHOD': message.method,
39
- 'QUERY_STRING': uri_parts.query or '',
40
- 'RAW_URI': message.path,
41
- 'SERVER_PROTOCOL': 'HTTP/%s.%s' % message.version,
33
+ 'REQUEST_METHOD': request.method,
34
+ 'QUERY_STRING': request.query_string or '',
35
+ 'RAW_URI': request.path_qs,
36
+ 'SERVER_PROTOCOL': f'HTTP/{request.version[0]}.{request.version[1]}',
42
37
  'REMOTE_ADDR': '127.0.0.1',
43
38
  'REMOTE_PORT': '0',
44
39
  'SERVER_NAME': 'aiohttp',
@@ -46,7 +41,7 @@ def translate_request(request):
46
41
  'aiohttp.request': request
47
42
  }
48
43
 
49
- for hdr_name, hdr_value in message.headers.items():
44
+ for hdr_name, hdr_value in request.headers.items():
50
45
  hdr_name = hdr_name.upper()
51
46
  if hdr_name == 'CONTENT-TYPE':
52
47
  environ['CONTENT_TYPE'] = hdr_value
@@ -63,9 +58,7 @@ def translate_request(request):
63
58
 
64
59
  environ['wsgi.url_scheme'] = environ.get('HTTP_X_FORWARDED_PROTO', 'http')
65
60
 
66
- path_info = uri_parts.path
67
-
68
- environ['PATH_INFO'] = path_info
61
+ environ['PATH_INFO'] = request.path
69
62
  environ['SCRIPT_NAME'] = ''
70
63
 
71
64
  return environ
@@ -105,7 +98,7 @@ class WebSocket: # pragma: no cover
105
98
  f = self._sock.send_bytes
106
99
  else:
107
100
  f = self._sock.send_str
108
- if asyncio.iscoroutinefunction(f):
101
+ if inspect.iscoroutinefunction(f):
109
102
  await f(message)
110
103
  else:
111
104
  f(message)
@@ -1,6 +1,6 @@
1
+ import inspect
1
2
  import os
2
3
  import sys
3
- import asyncio
4
4
 
5
5
  from engineio.static_files import get_static_file
6
6
 
@@ -102,7 +102,7 @@ class ASGIApp:
102
102
  if self.on_startup:
103
103
  try:
104
104
  await self.on_startup() \
105
- if asyncio.iscoroutinefunction(self.on_startup) \
105
+ if inspect.iscoroutinefunction(self.on_startup) \
106
106
  else self.on_startup()
107
107
  except:
108
108
  await send({'type': 'lifespan.startup.failed'})
@@ -112,7 +112,7 @@ class ASGIApp:
112
112
  if self.on_shutdown:
113
113
  try:
114
114
  await self.on_shutdown() \
115
- if asyncio.iscoroutinefunction(self.on_shutdown) \
115
+ if inspect.iscoroutinefunction(self.on_shutdown) \
116
116
  else self.on_shutdown()
117
117
  except:
118
118
  await send({'type': 'lifespan.shutdown.failed'})
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ import inspect
2
3
  import sys
3
4
  from urllib.parse import urlsplit
4
5
  from .. import exceptions
@@ -24,7 +25,7 @@ def get_tornado_handler(engineio_server):
24
25
  async def get(self, *args, **kwargs):
25
26
  if self.request.headers.get('Upgrade', '').lower() == 'websocket':
26
27
  ret = super().get(*args, **kwargs)
27
- if asyncio.iscoroutine(ret):
28
+ if inspect.iscoroutine(ret):
28
29
  await ret
29
30
  else:
30
31
  await engineio_server.handle_request(self)
@@ -1,4 +1,5 @@
1
1
  import asyncio
2
+ import inspect
2
3
  import urllib
3
4
 
4
5
  from . import base_server
@@ -56,8 +57,8 @@ class AsyncServer(base_server.BaseServer):
56
57
  :param cors_allowed_origins: Origin or list of origins that are allowed to
57
58
  connect to this server. Only the same origin
58
59
  is allowed by default. Set this argument to
59
- ``'*'`` to allow all origins, or to ``[]`` to
60
- disable CORS handling.
60
+ ``'*'`` or ``['*']`` to allow all origins, or
61
+ to ``[]`` to disable CORS handling.
61
62
  :param cors_credentials: Whether credentials (cookies, authentication) are
62
63
  allowed in requests to this server.
63
64
  :param logger: To enable logging set to ``True`` or pass a logger object to
@@ -212,7 +213,7 @@ class AsyncServer(base_server.BaseServer):
212
213
  Note: this method is a coroutine.
213
214
  """
214
215
  translate_request = self._async['translate_request']
215
- if asyncio.iscoroutinefunction(translate_request):
216
+ if inspect.iscoroutinefunction(translate_request):
216
217
  environ = await translate_request(*args, **kwargs)
217
218
  else:
218
219
  environ = translate_request(*args, **kwargs)
@@ -427,7 +428,7 @@ class AsyncServer(base_server.BaseServer):
427
428
  async def _make_response(self, response_dict, environ):
428
429
  cors_headers = self._cors_headers(environ)
429
430
  make_response = self._async['make_response']
430
- if asyncio.iscoroutinefunction(make_response):
431
+ if inspect.iscoroutinefunction(make_response):
431
432
  response = await make_response(
432
433
  response_dict['status'],
433
434
  response_dict['headers'] + cors_headers,
@@ -502,7 +503,7 @@ class AsyncServer(base_server.BaseServer):
502
503
  run_async = kwargs.pop('run_async', False)
503
504
  ret = None
504
505
  if event in self.handlers:
505
- if asyncio.iscoroutinefunction(self.handlers[event]):
506
+ if inspect.iscoroutinefunction(self.handlers[event]):
506
507
  async def run_async_handler():
507
508
  try:
508
509
  try:
@@ -310,7 +310,10 @@ class BaseServer:
310
310
  is_allowed = self.cors_allowed_origins(origin)
311
311
  allowed_origins = [origin] if is_allowed else []
312
312
  else:
313
- allowed_origins = self.cors_allowed_origins
313
+ if '*' in self.cors_allowed_origins:
314
+ allowed_origins = None
315
+ else:
316
+ allowed_origins = self.cors_allowed_origins
314
317
  return allowed_origins
315
318
 
316
319
  def _cors_headers(self, environ):
@@ -1,11 +1,12 @@
1
1
  from base64 import b64encode
2
- from engineio.json import JSONDecodeError
2
+ from http.cookies import SimpleCookie
3
3
  import logging
4
4
  import queue
5
5
  import ssl
6
6
  import threading
7
7
  import time
8
8
  import urllib
9
+ from engineio.json import JSONDecodeError
9
10
 
10
11
  try:
11
12
  import requests
@@ -173,6 +174,15 @@ class Client(base_client.BaseClient):
173
174
  """Create an event object."""
174
175
  return threading.Event(*args, **kwargs)
175
176
 
177
+ def _reset(self):
178
+ super()._reset()
179
+ while True: # pragma: no cover
180
+ try:
181
+ self.queue.get_nowait()
182
+ self.queue.task_done()
183
+ except self.queue_empty:
184
+ break
185
+
176
186
  def _connect_polling(self, url, headers, engineio_path):
177
187
  """Establish a long-polling connection to the Engine.IO server."""
178
188
  if requests is None: # pragma: no cover
@@ -259,8 +269,10 @@ class Client(base_client.BaseClient):
259
269
  extra_options = {}
260
270
  if self.http:
261
271
  # cookies
262
- cookies = '; '.join([f"{cookie.name}={cookie.value}"
263
- for cookie in self.http.cookies])
272
+ ck = SimpleCookie()
273
+ for cookie in self.http.cookies:
274
+ ck[cookie.name] = cookie.value
275
+ cookies = ck.output(header='', sep=';').strip()
264
276
  for header, value in headers.items():
265
277
  if header.lower() == 'cookie':
266
278
  if cookies:
@@ -54,8 +54,8 @@ class Server(base_server.BaseServer):
54
54
  :param cors_allowed_origins: Origin or list of origins that are allowed to
55
55
  connect to this server. Only the same origin
56
56
  is allowed by default. Set this argument to
57
- ``'*'`` to allow all origins, or to ``[]`` to
58
- disable CORS handling.
57
+ ``'*'`` or ``['*']`` to allow all origins, or
58
+ to ``[]`` to disable CORS handling.
59
59
  :param cors_credentials: Whether credentials (cookies, authentication) are
60
60
  allowed in requests to this server. The default
61
61
  is ``True``.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-engineio
3
- Version: 4.12.2
3
+ Version: 4.13.0
4
4
  Summary: Engine.IO server and client for Python
5
5
  Author-email: Miguel Grinberg <miguel.grinberg@gmail.com>
6
6
  License: MIT
@@ -10,7 +10,7 @@ Classifier: Environment :: Web Environment
10
10
  Classifier: Intended Audience :: Developers
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Operating System :: OS Independent
13
- Requires-Python: >=3.6
13
+ Requires-Python: >=3.8
14
14
  Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
16
  Requires-Dist: simple-websocket>=0.10.0
@@ -19,6 +19,8 @@ Requires-Dist: requests>=2.21.0; extra == "client"
19
19
  Requires-Dist: websocket-client>=0.54.0; extra == "client"
20
20
  Provides-Extra: asyncio-client
21
21
  Requires-Dist: aiohttp>=3.4; extra == "asyncio-client"
22
+ Provides-Extra: dev
23
+ Requires-Dist: tox; extra == "dev"
22
24
  Provides-Extra: docs
23
25
  Requires-Dist: sphinx; extra == "docs"
24
26
  Dynamic: license-file
@@ -7,5 +7,8 @@ aiohttp>=3.4
7
7
  requests>=2.21.0
8
8
  websocket-client>=0.54.0
9
9
 
10
+ [dev]
11
+ tox
12
+
10
13
  [docs]
11
14
  sphinx
@@ -1,5 +1,8 @@
1
1
  from unittest import mock
2
2
 
3
+ import yarl
4
+ from aiohttp.web import Request
5
+
3
6
  from engineio.async_drivers import aiohttp as async_aiohttp
4
7
 
5
8
 
@@ -12,18 +15,28 @@ class TestAiohttp:
12
15
  app.router.add_post.assert_any_call('/foo', mock_server.handle_request)
13
16
 
14
17
  def test_translate_request(self):
15
- request = mock.MagicMock()
16
- request._message.method = 'PUT'
17
- request._message.path = '/foo/bar?baz=1'
18
- request._message.version = (1, 1)
19
- request._message.headers = {
18
+ message = mock.MagicMock()
19
+ message.url = yarl.URL('https://example.com/foo/bar?baz=1')
20
+ message.method = 'PUT'
21
+ message.path = '/foo/bar?baz=1'
22
+ message.version = (1, 1)
23
+ message.headers = {
20
24
  'a': 'b',
21
25
  'c-c': 'd',
22
26
  'c_c': 'e',
23
27
  'content-type': 'application/json',
24
28
  'content-length': 123,
25
29
  }
26
- request._payload = b'hello world'
30
+
31
+ request = Request(
32
+ message,
33
+ payload=b'hello world',
34
+ protocol=mock.MagicMock(),
35
+ payload_writer=mock.MagicMock(),
36
+ task=mock.MagicMock(),
37
+ loop=mock.MagicMock(),
38
+ )
39
+
27
40
  environ = async_aiohttp.translate_request(request)
28
41
  expected_environ = {
29
42
  'REQUEST_METHOD': 'PUT',