uvicorn 0.28.0__py3-none-any.whl → 0.29.0__py3-none-any.whl
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.
- uvicorn/__init__.py +1 -1
- uvicorn/protocols/http/h11_impl.py +1 -4
- uvicorn/protocols/http/httptools_impl.py +2 -10
- uvicorn/server.py +25 -14
- {uvicorn-0.28.0.dist-info → uvicorn-0.29.0.dist-info}/METADATA +2 -2
- {uvicorn-0.28.0.dist-info → uvicorn-0.29.0.dist-info}/RECORD +9 -9
- {uvicorn-0.28.0.dist-info → uvicorn-0.29.0.dist-info}/WHEEL +1 -1
- {uvicorn-0.28.0.dist-info → uvicorn-0.29.0.dist-info}/entry_points.txt +0 -0
- {uvicorn-0.28.0.dist-info → uvicorn-0.29.0.dist-info}/licenses/LICENSE.md +0 -0
uvicorn/__init__.py
CHANGED
@@ -27,7 +27,6 @@ from uvicorn.protocols.http.flow_control import (
|
|
27
27
|
service_unavailable,
|
28
28
|
)
|
29
29
|
from uvicorn.protocols.utils import (
|
30
|
-
ClientDisconnected,
|
31
30
|
get_client_addr,
|
32
31
|
get_local_addr,
|
33
32
|
get_path_with_query_string,
|
@@ -408,8 +407,6 @@ class RequestResponseCycle:
|
|
408
407
|
result = await app( # type: ignore[func-returns-value]
|
409
408
|
self.scope, self.receive, self.send
|
410
409
|
)
|
411
|
-
except ClientDisconnected:
|
412
|
-
pass
|
413
410
|
except BaseException as exc:
|
414
411
|
msg = "Exception in ASGI application\n"
|
415
412
|
self.logger.error(msg, exc_info=exc)
|
@@ -458,7 +455,7 @@ class RequestResponseCycle:
|
|
458
455
|
await self.flow.drain()
|
459
456
|
|
460
457
|
if self.disconnected:
|
461
|
-
|
458
|
+
return
|
462
459
|
|
463
460
|
if not self.response_started:
|
464
461
|
# Sending response status line and headers
|
@@ -29,7 +29,6 @@ from uvicorn.protocols.http.flow_control import (
|
|
29
29
|
service_unavailable,
|
30
30
|
)
|
31
31
|
from uvicorn.protocols.utils import (
|
32
|
-
ClientDisconnected,
|
33
32
|
get_client_addr,
|
34
33
|
get_local_addr,
|
35
34
|
get_path_with_query_string,
|
@@ -412,8 +411,6 @@ class RequestResponseCycle:
|
|
412
411
|
result = await app( # type: ignore[func-returns-value]
|
413
412
|
self.scope, self.receive, self.send
|
414
413
|
)
|
415
|
-
except ClientDisconnected:
|
416
|
-
pass
|
417
414
|
except BaseException as exc:
|
418
415
|
msg = "Exception in ASGI application\n"
|
419
416
|
self.logger.error(msg, exc_info=exc)
|
@@ -462,7 +459,7 @@ class RequestResponseCycle:
|
|
462
459
|
await self.flow.drain()
|
463
460
|
|
464
461
|
if self.disconnected:
|
465
|
-
|
462
|
+
return
|
466
463
|
|
467
464
|
if not self.response_started:
|
468
465
|
# Sending response status line and headers
|
@@ -573,11 +570,6 @@ class RequestResponseCycle:
|
|
573
570
|
|
574
571
|
if self.disconnected or self.response_complete:
|
575
572
|
return {"type": "http.disconnect"}
|
576
|
-
|
577
|
-
message: HTTPRequestEvent = {
|
578
|
-
"type": "http.request",
|
579
|
-
"body": self.body,
|
580
|
-
"more_body": self.more_body,
|
581
|
-
}
|
573
|
+
message: HTTPRequestEvent = {"type": "http.request", "body": self.body, "more_body": self.more_body}
|
582
574
|
self.body = b""
|
583
575
|
return message
|
uvicorn/server.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import asyncio
|
4
|
+
import contextlib
|
4
5
|
import logging
|
5
6
|
import os
|
6
7
|
import platform
|
@@ -11,7 +12,7 @@ import threading
|
|
11
12
|
import time
|
12
13
|
from email.utils import formatdate
|
13
14
|
from types import FrameType
|
14
|
-
from typing import TYPE_CHECKING, Sequence, Union
|
15
|
+
from typing import TYPE_CHECKING, Generator, Sequence, Union
|
15
16
|
|
16
17
|
import click
|
17
18
|
|
@@ -57,11 +58,17 @@ class Server:
|
|
57
58
|
self.force_exit = False
|
58
59
|
self.last_notified = 0.0
|
59
60
|
|
61
|
+
self._captured_signals: list[int] = []
|
62
|
+
|
60
63
|
def run(self, sockets: list[socket.socket] | None = None) -> None:
|
61
64
|
self.config.setup_event_loop()
|
62
65
|
return asyncio.run(self.serve(sockets=sockets))
|
63
66
|
|
64
67
|
async def serve(self, sockets: list[socket.socket] | None = None) -> None:
|
68
|
+
with self.capture_signals():
|
69
|
+
await self._serve(sockets)
|
70
|
+
|
71
|
+
async def _serve(self, sockets: list[socket.socket] | None = None) -> None:
|
65
72
|
process_id = os.getpid()
|
66
73
|
|
67
74
|
config = self.config
|
@@ -70,8 +77,6 @@ class Server:
|
|
70
77
|
|
71
78
|
self.lifespan = config.lifespan_class(config)
|
72
79
|
|
73
|
-
self.install_signal_handlers()
|
74
|
-
|
75
80
|
message = "Started server process [%d]"
|
76
81
|
color_message = "Started server process [" + click.style("%d", fg="cyan") + "]"
|
77
82
|
logger.info(message, process_id, extra={"color_message": color_message})
|
@@ -302,22 +307,28 @@ class Server:
|
|
302
307
|
for server in self.servers:
|
303
308
|
await server.wait_closed()
|
304
309
|
|
305
|
-
|
310
|
+
@contextlib.contextmanager
|
311
|
+
def capture_signals(self) -> Generator[None, None, None]:
|
312
|
+
# Signals can only be listened to from the main thread.
|
306
313
|
if threading.current_thread() is not threading.main_thread():
|
307
|
-
|
314
|
+
yield
|
308
315
|
return
|
309
|
-
|
310
|
-
|
311
|
-
|
316
|
+
# always use signal.signal, even if loop.add_signal_handler is available
|
317
|
+
# this allows to restore previous signal handlers later on
|
318
|
+
original_handlers = {sig: signal.signal(sig, self.handle_exit) for sig in HANDLED_SIGNALS}
|
312
319
|
try:
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
320
|
+
yield
|
321
|
+
finally:
|
322
|
+
for sig, handler in original_handlers.items():
|
323
|
+
signal.signal(sig, handler)
|
324
|
+
# If we did gracefully shut down due to a signal, try to
|
325
|
+
# trigger the expected behaviour now; multiple signals would be
|
326
|
+
# done LIFO, see https://stackoverflow.com/questions/48434964
|
327
|
+
for captured_signal in reversed(self._captured_signals):
|
328
|
+
signal.raise_signal(captured_signal)
|
319
329
|
|
320
330
|
def handle_exit(self, sig: int, frame: FrameType | None) -> None:
|
331
|
+
self._captured_signals.append(sig)
|
321
332
|
if self.should_exit and sig == signal.SIGINT:
|
322
333
|
self.force_exit = True
|
323
334
|
else:
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: uvicorn
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.29.0
|
4
4
|
Summary: The lightning-fast ASGI server.
|
5
5
|
Project-URL: Changelog, https://github.com/encode/uvicorn/blob/master/CHANGELOG.md
|
6
6
|
Project-URL: Funding, https://github.com/sponsors/encode
|
@@ -1,4 +1,4 @@
|
|
1
|
-
uvicorn/__init__.py,sha256=
|
1
|
+
uvicorn/__init__.py,sha256=k39dO_sJjc5r3ZBUCrR15zL0qmWLLSJMhsiN_NDAiKo,147
|
2
2
|
uvicorn/__main__.py,sha256=DQizy6nKP0ywhPpnCHgmRDYIMfcqZKVEzNIWQZjqtVQ,62
|
3
3
|
uvicorn/_subprocess.py,sha256=wIxSuARuoouCXdLAVQCc2-MNv9utuTCpD9BsmLeqsvE,2505
|
4
4
|
uvicorn/_types.py,sha256=uJ4IRbis4frxIuO2mfCQu2OCToLRSFKp8foKIGwMjII,7793
|
@@ -7,7 +7,7 @@ uvicorn/importer.py,sha256=nRt0QQ3qpi264-n_mR0l55C2ddM8nowTNzT1jsWaam8,1128
|
|
7
7
|
uvicorn/logging.py,sha256=sg4D9lHaW_kKQj_kmP-bolbChjKfhBuihktlWp8RjSI,4236
|
8
8
|
uvicorn/main.py,sha256=uixfAm9Mfymxr2ZCA_YNy9avkD9Ljyv5onaSgF_bMZc,16565
|
9
9
|
uvicorn/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
10
|
-
uvicorn/server.py,sha256=
|
10
|
+
uvicorn/server.py,sha256=bXpsRamwT2cRoe7u6Nk8Czp_la2sfSnV9V0dva5-gkE,12729
|
11
11
|
uvicorn/workers.py,sha256=WhPoxhxvwebxP69DCfNYo_1mIOC7nIUTeC0wrrjiL3g,3667
|
12
12
|
uvicorn/lifespan/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
uvicorn/lifespan/off.py,sha256=nfI6qHAUo_8-BEXMBKoHQ9wUbsXrPaXLCbDSS0vKSr8,332
|
@@ -26,8 +26,8 @@ uvicorn/protocols/utils.py,sha256=Gt3UTpWnMNduq-hif4UocEkWjdkw7Us0OxMrejHIElA,18
|
|
26
26
|
uvicorn/protocols/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
27
|
uvicorn/protocols/http/auto.py,sha256=YfXGyzWTaaE2p_jkTPWrJCXsxEaQnC3NK0-G7Wgmnls,403
|
28
28
|
uvicorn/protocols/http/flow_control.py,sha256=yFt2GpEfugpuPiwCL7bAh8hd9Eub8V8THUJQ8ttDiiU,1771
|
29
|
-
uvicorn/protocols/http/h11_impl.py,sha256=
|
30
|
-
uvicorn/protocols/http/httptools_impl.py,sha256=
|
29
|
+
uvicorn/protocols/http/h11_impl.py,sha256=fJ9KeGIme-OdLxt7_wrm5VwlDIFtWMw00edgjgN2P0E,20376
|
30
|
+
uvicorn/protocols/http/httptools_impl.py,sha256=Ei77FJPorqq8d3C-YGUe9eTLDnX6afaBsoEfj7xtE5Y,21462
|
31
31
|
uvicorn/protocols/websockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
32
32
|
uvicorn/protocols/websockets/auto.py,sha256=kNP-h07ZzjA9dKRUd7MNO0J7xhRJ5xVBfit7wCbdB0A,574
|
33
33
|
uvicorn/protocols/websockets/websockets_impl.py,sha256=fIbUdUJZZhx6KdBBj8nG56pkZtNeMWj_QxRgg17bmtQ,15234
|
@@ -38,8 +38,8 @@ uvicorn/supervisors/multiprocess.py,sha256=vBGBBq4vQcSdghev-kGjtBPGMwCyTNs1IE6Ne
|
|
38
38
|
uvicorn/supervisors/statreload.py,sha256=gc-HUB44f811PvxD_ZIEQYenM7mWmhQQjYg7KKQ1c5o,1542
|
39
39
|
uvicorn/supervisors/watchfilesreload.py,sha256=RMhWgInlOr0MJB0RvmW50RZY1ls9Kp9VT3eaLjdRTpw,2935
|
40
40
|
uvicorn/supervisors/watchgodreload.py,sha256=kd-gOvp14ArTNIc206Nt5CEjZZ4NP2UmMVYE7571yRQ,5486
|
41
|
-
uvicorn-0.
|
42
|
-
uvicorn-0.
|
43
|
-
uvicorn-0.
|
44
|
-
uvicorn-0.
|
45
|
-
uvicorn-0.
|
41
|
+
uvicorn-0.29.0.dist-info/METADATA,sha256=7eFKWJYud857eJfc05LZwrXIOAWcwdyFZN8pMqo-afM,6330
|
42
|
+
uvicorn-0.29.0.dist-info/WHEEL,sha256=bq9SyP5NxIRA9EpQgMCd-9RmPHWvbH-4lTDGwxgIR64,87
|
43
|
+
uvicorn-0.29.0.dist-info/entry_points.txt,sha256=FW1w-hkc9QgwaGoovMvm0ZY73w_NcycWdGAUfDsNGxw,46
|
44
|
+
uvicorn-0.29.0.dist-info/licenses/LICENSE.md,sha256=7-Gs8-YvuZwoiw7HPlp3O3Jo70Mg_nV-qZQhTktjw3E,1526
|
45
|
+
uvicorn-0.29.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|