uvicorn 0.34.3__py3-none-any.whl → 0.35.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 CHANGED
@@ -1,5 +1,5 @@
1
1
  from uvicorn.config import Config
2
2
  from uvicorn.main import Server, main, run
3
3
 
4
- __version__ = "0.34.3"
4
+ __version__ = "0.35.0"
5
5
  __all__ = ["main", "run", "Config", "Server"]
uvicorn/config.py CHANGED
@@ -25,7 +25,7 @@ from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
25
25
  from uvicorn.middleware.wsgi import WSGIMiddleware
26
26
 
27
27
  HTTPProtocolType = Literal["auto", "h11", "httptools"]
28
- WSProtocolType = Literal["auto", "none", "websockets", "wsproto"]
28
+ WSProtocolType = Literal["auto", "none", "websockets", "websockets-sansio", "wsproto"]
29
29
  LifespanType = Literal["auto", "on", "off"]
30
30
  LoopSetupType = Literal["none", "auto", "asyncio", "uvloop"]
31
31
  InterfaceType = Literal["auto", "asgi3", "asgi2", "wsgi"]
@@ -47,6 +47,7 @@ WS_PROTOCOLS: dict[WSProtocolType, str | None] = {
47
47
  "auto": "uvicorn.protocols.websockets.auto:AutoWebSocketsProtocol",
48
48
  "none": None,
49
49
  "websockets": "uvicorn.protocols.websockets.websockets_impl:WebSocketProtocol",
50
+ "websockets-sansio": "uvicorn.protocols.websockets.websockets_sansio_impl:WebSocketsSansIOProtocol",
50
51
  "wsproto": "uvicorn.protocols.websockets.wsproto_impl:WSProtocol",
51
52
  }
52
53
  LIFESPAN: dict[LifespanType, str] = {
uvicorn/main.py CHANGED
@@ -223,7 +223,7 @@ def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> No
223
223
  "--proxy-headers/--no-proxy-headers",
224
224
  is_flag=True,
225
225
  default=True,
226
- help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info.",
226
+ help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For to populate url scheme and remote address info.",
227
227
  )
228
228
  @click.option(
229
229
  "--server-header/--no-server-header",
@@ -0,0 +1,417 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import logging
5
+ import sys
6
+ from asyncio.transports import BaseTransport, Transport
7
+ from http import HTTPStatus
8
+ from typing import Any, Literal, cast
9
+ from urllib.parse import unquote
10
+
11
+ from websockets.exceptions import InvalidState
12
+ from websockets.extensions.permessage_deflate import ServerPerMessageDeflateFactory
13
+ from websockets.frames import Frame, Opcode
14
+ from websockets.http11 import Request
15
+ from websockets.server import ServerProtocol
16
+
17
+ from uvicorn._types import (
18
+ ASGIReceiveEvent,
19
+ ASGISendEvent,
20
+ WebSocketAcceptEvent,
21
+ WebSocketCloseEvent,
22
+ WebSocketResponseBodyEvent,
23
+ WebSocketResponseStartEvent,
24
+ WebSocketScope,
25
+ WebSocketSendEvent,
26
+ )
27
+ from uvicorn.config import Config
28
+ from uvicorn.logging import TRACE_LOG_LEVEL
29
+ from uvicorn.protocols.utils import (
30
+ ClientDisconnected,
31
+ get_local_addr,
32
+ get_path_with_query_string,
33
+ get_remote_addr,
34
+ is_ssl,
35
+ )
36
+ from uvicorn.server import ServerState
37
+
38
+ if sys.version_info >= (3, 11): # pragma: no cover
39
+ from typing import assert_never
40
+ else: # pragma: no cover
41
+ from typing_extensions import assert_never
42
+
43
+
44
+ class WebSocketsSansIOProtocol(asyncio.Protocol):
45
+ def __init__(
46
+ self,
47
+ config: Config,
48
+ server_state: ServerState,
49
+ app_state: dict[str, Any],
50
+ _loop: asyncio.AbstractEventLoop | None = None,
51
+ ) -> None:
52
+ if not config.loaded:
53
+ config.load() # pragma: no cover
54
+
55
+ self.config = config
56
+ self.app = config.loaded_app
57
+ self.loop = _loop or asyncio.get_event_loop()
58
+ self.logger = logging.getLogger("uvicorn.error")
59
+ self.root_path = config.root_path
60
+ self.app_state = app_state
61
+
62
+ # Shared server state
63
+ self.connections = server_state.connections
64
+ self.tasks = server_state.tasks
65
+ self.default_headers = server_state.default_headers
66
+
67
+ # Connection state
68
+ self.transport: asyncio.Transport = None # type: ignore[assignment]
69
+ self.server: tuple[str, int] | None = None
70
+ self.client: tuple[str, int] | None = None
71
+ self.scheme: Literal["wss", "ws"] = None # type: ignore[assignment]
72
+
73
+ # WebSocket state
74
+ self.queue: asyncio.Queue[ASGIReceiveEvent] = asyncio.Queue()
75
+ self.handshake_initiated = False
76
+ self.handshake_complete = False
77
+ self.close_sent = False
78
+ self.initial_response: tuple[int, list[tuple[str, str]], bytes] | None = None
79
+
80
+ extensions = []
81
+ if self.config.ws_per_message_deflate:
82
+ extensions = [
83
+ ServerPerMessageDeflateFactory(
84
+ server_max_window_bits=12,
85
+ client_max_window_bits=12,
86
+ compress_settings={"memLevel": 5},
87
+ )
88
+ ]
89
+ self.conn = ServerProtocol(
90
+ extensions=extensions,
91
+ max_size=self.config.ws_max_size,
92
+ logger=logging.getLogger("uvicorn.error"),
93
+ )
94
+
95
+ self.read_paused = False
96
+ self.writable = asyncio.Event()
97
+ self.writable.set()
98
+
99
+ # Buffers
100
+ self.bytes = b""
101
+
102
+ def connection_made(self, transport: BaseTransport) -> None:
103
+ """Called when a connection is made."""
104
+ transport = cast(Transport, transport)
105
+ self.connections.add(self)
106
+ self.transport = transport
107
+ self.server = get_local_addr(transport)
108
+ self.client = get_remote_addr(transport)
109
+ self.scheme = "wss" if is_ssl(transport) else "ws"
110
+
111
+ if self.logger.level <= TRACE_LOG_LEVEL:
112
+ prefix = "%s:%d - " % self.client if self.client else ""
113
+ self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection made", prefix)
114
+
115
+ def connection_lost(self, exc: Exception | None) -> None:
116
+ code = 1005 if self.handshake_complete else 1006
117
+ self.queue.put_nowait({"type": "websocket.disconnect", "code": code})
118
+ self.connections.remove(self)
119
+
120
+ if self.logger.level <= TRACE_LOG_LEVEL:
121
+ prefix = "%s:%d - " % self.client if self.client else ""
122
+ self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection lost", prefix)
123
+
124
+ self.handshake_complete = True
125
+ if exc is None:
126
+ self.transport.close()
127
+
128
+ def eof_received(self) -> None:
129
+ pass
130
+
131
+ def shutdown(self) -> None:
132
+ if self.handshake_complete:
133
+ self.queue.put_nowait({"type": "websocket.disconnect", "code": 1012})
134
+ self.conn.send_close(1012)
135
+ output = self.conn.data_to_send()
136
+ self.transport.write(b"".join(output))
137
+ else:
138
+ self.send_500_response()
139
+ self.transport.close()
140
+
141
+ def data_received(self, data: bytes) -> None:
142
+ self.conn.receive_data(data)
143
+ if self.conn.parser_exc is not None: # pragma: no cover
144
+ self.handle_parser_exception()
145
+ return
146
+ self.handle_events()
147
+
148
+ def handle_events(self) -> None:
149
+ for event in self.conn.events_received():
150
+ if isinstance(event, Request):
151
+ self.handle_connect(event)
152
+ if isinstance(event, Frame):
153
+ if event.opcode == Opcode.CONT:
154
+ self.handle_cont(event) # pragma: no cover
155
+ elif event.opcode == Opcode.TEXT:
156
+ self.handle_text(event)
157
+ elif event.opcode == Opcode.BINARY:
158
+ self.handle_bytes(event)
159
+ elif event.opcode == Opcode.PING:
160
+ self.handle_ping()
161
+ elif event.opcode == Opcode.PONG:
162
+ pass # pragma: no cover
163
+ elif event.opcode == Opcode.CLOSE:
164
+ self.handle_close(event)
165
+ else:
166
+ assert_never(event.opcode) # pragma: no cover
167
+
168
+ # Event handlers
169
+
170
+ def handle_connect(self, event: Request) -> None:
171
+ self.request = event
172
+ self.response = self.conn.accept(event)
173
+ self.handshake_initiated = True
174
+ if self.response.status_code != 101:
175
+ self.handshake_complete = True
176
+ self.close_sent = True
177
+ self.conn.send_response(self.response)
178
+ output = self.conn.data_to_send()
179
+ self.transport.write(b"".join(output))
180
+ self.transport.close()
181
+ return
182
+
183
+ headers = [
184
+ (key.encode("ascii"), value.encode("ascii", errors="surrogateescape"))
185
+ for key, value in event.headers.raw_items()
186
+ ]
187
+ raw_path, _, query_string = event.path.partition("?")
188
+ self.scope: WebSocketScope = {
189
+ "type": "websocket",
190
+ "asgi": {"version": self.config.asgi_version, "spec_version": "2.3"},
191
+ "http_version": "1.1",
192
+ "scheme": self.scheme,
193
+ "server": self.server,
194
+ "client": self.client,
195
+ "root_path": self.root_path,
196
+ "path": unquote(raw_path),
197
+ "raw_path": raw_path.encode("ascii"),
198
+ "query_string": query_string.encode("ascii"),
199
+ "headers": headers,
200
+ "subprotocols": event.headers.get_all("Sec-WebSocket-Protocol"),
201
+ "state": self.app_state.copy(),
202
+ "extensions": {"websocket.http.response": {}},
203
+ }
204
+ self.queue.put_nowait({"type": "websocket.connect"})
205
+ task = self.loop.create_task(self.run_asgi())
206
+ task.add_done_callback(self.on_task_complete)
207
+ self.tasks.add(task)
208
+
209
+ def handle_cont(self, event: Frame) -> None: # pragma: no cover
210
+ self.bytes += event.data
211
+ if event.fin:
212
+ self.send_receive_event_to_app()
213
+
214
+ def handle_text(self, event: Frame) -> None:
215
+ self.bytes = event.data
216
+ self.curr_msg_data_type: Literal["text", "bytes"] = "text"
217
+ if event.fin:
218
+ self.send_receive_event_to_app()
219
+
220
+ def handle_bytes(self, event: Frame) -> None:
221
+ self.bytes = event.data
222
+ self.curr_msg_data_type = "bytes"
223
+ if event.fin:
224
+ self.send_receive_event_to_app()
225
+
226
+ def send_receive_event_to_app(self) -> None:
227
+ if self.curr_msg_data_type == "text":
228
+ try:
229
+ self.queue.put_nowait({"type": "websocket.receive", "text": self.bytes.decode()})
230
+ except UnicodeDecodeError: # pragma: no cover
231
+ self.logger.exception("Invalid UTF-8 sequence received from client.")
232
+ self.conn.send_close(1007)
233
+ self.handle_parser_exception()
234
+ return
235
+ else:
236
+ self.queue.put_nowait({"type": "websocket.receive", "bytes": self.bytes})
237
+ if not self.read_paused:
238
+ self.read_paused = True
239
+ self.transport.pause_reading()
240
+
241
+ def handle_ping(self) -> None:
242
+ output = self.conn.data_to_send()
243
+ self.transport.write(b"".join(output))
244
+
245
+ def handle_close(self, event: Frame) -> None:
246
+ if not self.close_sent and not self.transport.is_closing():
247
+ assert self.conn.close_rcvd is not None
248
+ code = self.conn.close_rcvd.code
249
+ reason = self.conn.close_rcvd.reason
250
+ self.queue.put_nowait({"type": "websocket.disconnect", "code": code, "reason": reason})
251
+
252
+ output = self.conn.data_to_send()
253
+ self.transport.write(b"".join(output))
254
+ self.transport.close()
255
+
256
+ def handle_parser_exception(self) -> None: # pragma: no cover
257
+ assert self.conn.close_sent is not None
258
+ code = self.conn.close_sent.code
259
+ reason = self.conn.close_sent.reason
260
+ self.queue.put_nowait({"type": "websocket.disconnect", "code": code, "reason": reason})
261
+
262
+ output = self.conn.data_to_send()
263
+ self.transport.write(b"".join(output))
264
+ self.close_sent = True
265
+ self.transport.close()
266
+
267
+ def on_task_complete(self, task: asyncio.Task[None]) -> None:
268
+ self.tasks.discard(task)
269
+
270
+ async def run_asgi(self) -> None:
271
+ try:
272
+ result = await self.app(self.scope, self.receive, self.send)
273
+ except ClientDisconnected:
274
+ self.transport.close() # pragma: no cover
275
+ except BaseException:
276
+ self.logger.exception("Exception in ASGI application\n")
277
+ self.send_500_response()
278
+ self.transport.close()
279
+ else:
280
+ if not self.handshake_complete:
281
+ self.logger.error("ASGI callable returned without completing handshake.")
282
+ self.send_500_response()
283
+ self.transport.close()
284
+ elif result is not None:
285
+ self.logger.error("ASGI callable should return None, but returned '%s'.", result)
286
+ self.transport.close()
287
+
288
+ def send_500_response(self) -> None:
289
+ if self.initial_response or self.handshake_complete:
290
+ return
291
+ response = self.conn.reject(500, "Internal Server Error")
292
+ self.conn.send_response(response)
293
+ output = self.conn.data_to_send()
294
+ self.transport.write(b"".join(output))
295
+
296
+ async def send(self, message: ASGISendEvent) -> None:
297
+ await self.writable.wait()
298
+
299
+ message_type = message["type"]
300
+
301
+ if not self.handshake_complete and self.initial_response is None:
302
+ if message_type == "websocket.accept":
303
+ message = cast(WebSocketAcceptEvent, message)
304
+ self.logger.info(
305
+ '%s - "WebSocket %s" [accepted]',
306
+ self.scope["client"],
307
+ get_path_with_query_string(self.scope),
308
+ )
309
+ headers = [
310
+ (name.decode("latin-1").lower(), value.decode("latin-1").lower())
311
+ for name, value in (self.default_headers + list(message.get("headers", [])))
312
+ ]
313
+ accepted_subprotocol = message.get("subprotocol")
314
+ if accepted_subprotocol:
315
+ headers.append(("Sec-WebSocket-Protocol", accepted_subprotocol))
316
+ self.response.headers.update(headers)
317
+
318
+ if not self.transport.is_closing():
319
+ self.handshake_complete = True
320
+ self.conn.send_response(self.response)
321
+ output = self.conn.data_to_send()
322
+ self.transport.write(b"".join(output))
323
+
324
+ elif message_type == "websocket.close":
325
+ message = cast(WebSocketCloseEvent, message)
326
+ self.queue.put_nowait({"type": "websocket.disconnect", "code": 1006})
327
+ self.logger.info(
328
+ '%s - "WebSocket %s" 403',
329
+ self.scope["client"],
330
+ get_path_with_query_string(self.scope),
331
+ )
332
+ response = self.conn.reject(HTTPStatus.FORBIDDEN, "")
333
+ self.conn.send_response(response)
334
+ output = self.conn.data_to_send()
335
+ self.close_sent = True
336
+ self.handshake_complete = True
337
+ self.transport.write(b"".join(output))
338
+ self.transport.close()
339
+ elif message_type == "websocket.http.response.start" and self.initial_response is None:
340
+ message = cast(WebSocketResponseStartEvent, message)
341
+ if not (100 <= message["status"] < 600):
342
+ raise RuntimeError("Invalid HTTP status code '%d' in response." % message["status"])
343
+ self.logger.info(
344
+ '%s - "WebSocket %s" %d',
345
+ self.scope["client"],
346
+ get_path_with_query_string(self.scope),
347
+ message["status"],
348
+ )
349
+ headers = [
350
+ (name.decode("latin-1"), value.decode("latin-1"))
351
+ for name, value in list(message.get("headers", []))
352
+ ]
353
+ self.initial_response = (message["status"], headers, b"")
354
+ else:
355
+ msg = (
356
+ "Expected ASGI message 'websocket.accept', 'websocket.close' "
357
+ "or 'websocket.http.response.start' "
358
+ "but got '%s'."
359
+ )
360
+ raise RuntimeError(msg % message_type)
361
+
362
+ elif not self.close_sent and self.initial_response is None:
363
+ try:
364
+ if message_type == "websocket.send":
365
+ message = cast(WebSocketSendEvent, message)
366
+ bytes_data = message.get("bytes")
367
+ text_data = message.get("text")
368
+ if text_data:
369
+ self.conn.send_text(text_data.encode())
370
+ elif bytes_data:
371
+ self.conn.send_binary(bytes_data)
372
+ output = self.conn.data_to_send()
373
+ self.transport.write(b"".join(output))
374
+
375
+ elif message_type == "websocket.close" and not self.transport.is_closing():
376
+ message = cast(WebSocketCloseEvent, message)
377
+ code = message.get("code", 1000)
378
+ reason = message.get("reason", "") or ""
379
+ self.queue.put_nowait({"type": "websocket.disconnect", "code": code, "reason": reason})
380
+ self.conn.send_close(code, reason)
381
+ output = self.conn.data_to_send()
382
+ self.transport.write(b"".join(output))
383
+ self.close_sent = True
384
+ self.transport.close()
385
+ else:
386
+ msg = "Expected ASGI message 'websocket.send' or 'websocket.close', but got '%s'."
387
+ raise RuntimeError(msg % message_type)
388
+ except InvalidState:
389
+ raise ClientDisconnected()
390
+ elif self.initial_response is not None:
391
+ if message_type == "websocket.http.response.body":
392
+ message = cast(WebSocketResponseBodyEvent, message)
393
+ body = self.initial_response[2] + message["body"]
394
+ self.initial_response = self.initial_response[:2] + (body,)
395
+ if not message.get("more_body", False):
396
+ response = self.conn.reject(self.initial_response[0], body.decode())
397
+ response.headers.update(self.initial_response[1])
398
+ self.queue.put_nowait({"type": "websocket.disconnect", "code": 1006})
399
+ self.conn.send_response(response)
400
+ output = self.conn.data_to_send()
401
+ self.close_sent = True
402
+ self.transport.write(b"".join(output))
403
+ self.transport.close()
404
+ else: # pragma: no cover
405
+ msg = "Expected ASGI message 'websocket.http.response.body' but got '%s'."
406
+ raise RuntimeError(msg % message_type)
407
+
408
+ else:
409
+ msg = "Unexpected ASGI message '%s', after sending 'websocket.close'."
410
+ raise RuntimeError(msg % message_type)
411
+
412
+ async def receive(self) -> ASGIReceiveEvent:
413
+ message = await self.queue.get()
414
+ if self.read_paused and self.queue.empty():
415
+ self.read_paused = False
416
+ self.transport.resume_reading()
417
+ return message
uvicorn/server.py CHANGED
@@ -23,9 +23,10 @@ if TYPE_CHECKING:
23
23
  from uvicorn.protocols.http.h11_impl import H11Protocol
24
24
  from uvicorn.protocols.http.httptools_impl import HttpToolsProtocol
25
25
  from uvicorn.protocols.websockets.websockets_impl import WebSocketProtocol
26
+ from uvicorn.protocols.websockets.websockets_sansio_impl import WebSocketsSansIOProtocol
26
27
  from uvicorn.protocols.websockets.wsproto_impl import WSProtocol
27
28
 
28
- Protocols = Union[H11Protocol, HttpToolsProtocol, WSProtocol, WebSocketProtocol]
29
+ Protocols = Union[H11Protocol, HttpToolsProtocol, WSProtocol, WebSocketProtocol, WebSocketsSansIOProtocol]
29
30
 
30
31
  HANDLED_SIGNALS = (
31
32
  signal.SIGINT, # Unix signal 2. Sent by Ctrl+C.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uvicorn
3
- Version: 0.34.3
3
+ Version: 0.35.0
4
4
  Summary: The lightning-fast ASGI server.
5
5
  Project-URL: Changelog, https://www.uvicorn.org/release-notes
6
6
  Project-URL: Funding, https://github.com/sponsors/encode
@@ -1,13 +1,13 @@
1
- uvicorn/__init__.py,sha256=4LwEp7joIjTJGVCgzB4GQTAoFBH4AYD2O-EPCYxWt6M,147
1
+ uvicorn/__init__.py,sha256=pMIkABPLJ9eS0OuDO-bP506aVdLfWlHDtk9uzSTgE5E,147
2
2
  uvicorn/__main__.py,sha256=DQizy6nKP0ywhPpnCHgmRDYIMfcqZKVEzNIWQZjqtVQ,62
3
3
  uvicorn/_subprocess.py,sha256=HbfRnsCkXyg7xCWVAWWzXQTeWlvLKfTlIF5wevFBkR4,2766
4
4
  uvicorn/_types.py,sha256=5FcPvvIfeKsJDjGhTrceDv8TmwzYI8yPF7mXsXTWOUM,7775
5
- uvicorn/config.py,sha256=J6tdBhwecNgUJHX0CbIYHJ828Sl3WKyercf6QhSzGmM,20887
5
+ uvicorn/config.py,sha256=OHgnEBBuk7XMhwKByt1hlBJsXk8EGWRYGpCQ_G1deaA,21013
6
6
  uvicorn/importer.py,sha256=nRt0QQ3qpi264-n_mR0l55C2ddM8nowTNzT1jsWaam8,1128
7
7
  uvicorn/logging.py,sha256=-eCE4nOJmFbtB9qfNJuEVNF0Y13LGUHqvFzemYT0PaQ,4235
8
- uvicorn/main.py,sha256=5TFzub2UbSk4LOQ_UeQ3PZLiTRG51KIQ0sSY9SZUMN8,17234
8
+ uvicorn/main.py,sha256=83-MEMVc6ErEdvUfW6x-gELYJ78GiWRNMsmuing9DUI,17231
9
9
  uvicorn/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
10
- uvicorn/server.py,sha256=Kd2S0UarzwJyt9YHZzTghMPxxRVa1zIVA8Cqy6AuT9A,12879
10
+ uvicorn/server.py,sha256=3AKFM50WbZkwnqjZFxSd8wLBVIkcxZjmvP8gPZf95_s,12998
11
11
  uvicorn/workers.py,sha256=7KGgGAapxGkGeXUcBGunOjSNdI9R44KCoWTGEAqAdfs,3895
12
12
  uvicorn/lifespan/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  uvicorn/lifespan/off.py,sha256=nfI6qHAUo_8-BEXMBKoHQ9wUbsXrPaXLCbDSS0vKSr8,332
@@ -31,14 +31,15 @@ uvicorn/protocols/http/httptools_impl.py,sha256=tuQBCiD6rf5DQeyQwHVc45rxH9ouojMp
31
31
  uvicorn/protocols/websockets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
32
  uvicorn/protocols/websockets/auto.py,sha256=SH_KV_3vwR8_oGda2GrHFt38VG-IwY0ufjvHOu4VA0o,581
33
33
  uvicorn/protocols/websockets/websockets_impl.py,sha256=qonQJxz9wMKMwB2RnYZezeP-XfmAsxCvNeGgu4sC3Lc,15546
34
+ uvicorn/protocols/websockets/websockets_sansio_impl.py,sha256=TxpjkbuhaTd0UXYc1VMe4UgBr6kn_JwJV-hqegHHmxs,17145
34
35
  uvicorn/protocols/websockets/wsproto_impl.py,sha256=u2TKyzRUCmQpS1e4E_X6Uou9QIuoKZNNNmHU1IzkWPU,15366
35
36
  uvicorn/supervisors/__init__.py,sha256=wT8eOEIqT1yWQgytZtv5taWMul7xoTIY0xm1m4oyPTw,507
36
37
  uvicorn/supervisors/basereload.py,sha256=MAXSQ3ckZPwqzJ8Un9yDhk3W0yyAArQtZLuOE0OInSc,4036
37
38
  uvicorn/supervisors/multiprocess.py,sha256=Opt0XvOUj1DIMXYwb4OlkJZxeh_RjweFnTmDPYItONw,7507
38
39
  uvicorn/supervisors/statreload.py,sha256=uYblmoxM3IbPbvMDzr5Abw2-WykQl8NxTTzeLfVyvnU,1566
39
40
  uvicorn/supervisors/watchfilesreload.py,sha256=W86Ybb0E5SdMYYuWHJ3bpAFXdw5ZurvLRdFcvLnYEIA,2859
40
- uvicorn-0.34.3.dist-info/METADATA,sha256=RC1OrruxWAfCxWLXP-xUUok8GH9Pez4iIYFFum5dBnA,6531
41
- uvicorn-0.34.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
42
- uvicorn-0.34.3.dist-info/entry_points.txt,sha256=FW1w-hkc9QgwaGoovMvm0ZY73w_NcycWdGAUfDsNGxw,46
43
- uvicorn-0.34.3.dist-info/licenses/LICENSE.md,sha256=7-Gs8-YvuZwoiw7HPlp3O3Jo70Mg_nV-qZQhTktjw3E,1526
44
- uvicorn-0.34.3.dist-info/RECORD,,
41
+ uvicorn-0.35.0.dist-info/METADATA,sha256=a1sVo25u3fbfeGXSMmFdYOuPPnBXF8WjHlYq1oc2qTo,6531
42
+ uvicorn-0.35.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
43
+ uvicorn-0.35.0.dist-info/entry_points.txt,sha256=FW1w-hkc9QgwaGoovMvm0ZY73w_NcycWdGAUfDsNGxw,46
44
+ uvicorn-0.35.0.dist-info/licenses/LICENSE.md,sha256=7-Gs8-YvuZwoiw7HPlp3O3Jo70Mg_nV-qZQhTktjw3E,1526
45
+ uvicorn-0.35.0.dist-info/RECORD,,