uvicorn 0.27.1__py3-none-any.whl → 0.28.1__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.
@@ -43,9 +43,7 @@ def _get_status_phrase(status_code: int) -> bytes:
43
43
  return b""
44
44
 
45
45
 
46
- STATUS_PHRASES = {
47
- status_code: _get_status_phrase(status_code) for status_code in range(100, 600)
48
- }
46
+ STATUS_PHRASES = {status_code: _get_status_phrase(status_code) for status_code in range(100, 600)}
49
47
 
50
48
 
51
49
  class H11Protocol(asyncio.Protocol):
@@ -205,7 +203,7 @@ class H11Protocol(asyncio.Protocol):
205
203
  "type": "http",
206
204
  "asgi": {
207
205
  "version": self.config.asgi_version,
208
- "spec_version": "2.3",
206
+ "spec_version": "2.4",
209
207
  },
210
208
  "http_version": event.http_version.decode("ascii"),
211
209
  "server": self.server,
@@ -227,8 +225,7 @@ class H11Protocol(asyncio.Protocol):
227
225
 
228
226
  # Handle 503 responses when 'limit_concurrency' is exceeded.
229
227
  if self.limit_concurrency is not None and (
230
- len(self.connections) >= self.limit_concurrency
231
- or len(self.tasks) >= self.limit_concurrency
228
+ len(self.connections) >= self.limit_concurrency or len(self.tasks) >= self.limit_concurrency
232
229
  ):
233
230
  app = service_unavailable
234
231
  message = "Exceeded concurrency limit."
@@ -322,9 +319,7 @@ class H11Protocol(asyncio.Protocol):
322
319
  # Set a short Keep-Alive timeout.
323
320
  self._unset_keepalive_if_required()
324
321
 
325
- self.timeout_keep_alive_task = self.loop.call_later(
326
- self.timeout_keep_alive, self.timeout_keep_alive_handler
327
- )
322
+ self.timeout_keep_alive_task = self.loop.call_later(self.timeout_keep_alive, self.timeout_keep_alive_handler)
328
323
 
329
324
  # Unpause data reads if needed.
330
325
  self.flow.resume_reading()
@@ -371,7 +366,7 @@ class H11Protocol(asyncio.Protocol):
371
366
  class RequestResponseCycle:
372
367
  def __init__(
373
368
  self,
374
- scope: "HTTPScope",
369
+ scope: HTTPScope,
375
370
  conn: h11.Connection,
376
371
  transport: asyncio.Transport,
377
372
  flow: FlowControl,
@@ -407,7 +402,7 @@ class RequestResponseCycle:
407
402
  self.response_complete = False
408
403
 
409
404
  # ASGI exception wrapper
410
- async def run_asgi(self, app: "ASGI3Application") -> None:
405
+ async def run_asgi(self, app: ASGI3Application) -> None:
411
406
  try:
412
407
  result = await app( # type: ignore[func-returns-value]
413
408
  self.scope, self.receive, self.send
@@ -436,7 +431,7 @@ class RequestResponseCycle:
436
431
  self.on_response = lambda: None
437
432
 
438
433
  async def send_500_response(self) -> None:
439
- response_start_event: "HTTPResponseStartEvent" = {
434
+ response_start_event: HTTPResponseStartEvent = {
440
435
  "type": "http.response.start",
441
436
  "status": 500,
442
437
  "headers": [
@@ -445,7 +440,7 @@ class RequestResponseCycle:
445
440
  ],
446
441
  }
447
442
  await self.send(response_start_event)
448
- response_body_event: "HTTPResponseBodyEvent" = {
443
+ response_body_event: HTTPResponseBodyEvent = {
449
444
  "type": "http.response.body",
450
445
  "body": b"Internal Server Error",
451
446
  "more_body": False,
@@ -453,7 +448,7 @@ class RequestResponseCycle:
453
448
  await self.send(response_body_event)
454
449
 
455
450
  # ASGI interface
456
- async def send(self, message: "ASGISendEvent") -> None:
451
+ async def send(self, message: ASGISendEvent) -> None:
457
452
  message_type = message["type"]
458
453
 
459
454
  if self.flow.write_paused and not self.disconnected:
@@ -527,12 +522,10 @@ class RequestResponseCycle:
527
522
  self.transport.close()
528
523
  self.on_response()
529
524
 
530
- async def receive(self) -> "ASGIReceiveEvent":
525
+ async def receive(self) -> ASGIReceiveEvent:
531
526
  if self.waiting_for_100_continue and not self.transport.is_closing():
532
527
  headers: list[tuple[str, str]] = []
533
- event = h11.InformationalResponse(
534
- status_code=100, headers=headers, reason="Continue"
535
- )
528
+ event = h11.InformationalResponse(status_code=100, headers=headers, reason="Continue")
536
529
  output = self.conn.send(event=event)
537
530
  self.transport.write(output)
538
531
  self.waiting_for_100_continue = False
@@ -545,7 +538,7 @@ class RequestResponseCycle:
545
538
  if self.disconnected or self.response_complete:
546
539
  return {"type": "http.disconnect"}
547
540
 
548
- message: "HTTPRequestEvent" = {
541
+ message: HTTPRequestEvent = {
549
542
  "type": "http.request",
550
543
  "body": self.body,
551
544
  "more_body": self.more_body,
@@ -7,7 +7,7 @@ import re
7
7
  import urllib
8
8
  from asyncio.events import TimerHandle
9
9
  from collections import deque
10
- from typing import Any, Callable, Deque, Literal, cast
10
+ from typing import Any, Callable, Literal, cast
11
11
 
12
12
  import httptools
13
13
 
@@ -15,7 +15,6 @@ from uvicorn._types import (
15
15
  ASGI3Application,
16
16
  ASGIReceiveEvent,
17
17
  ASGISendEvent,
18
- HTTPDisconnectEvent,
19
18
  HTTPRequestEvent,
20
19
  HTTPResponseBodyEvent,
21
20
  HTTPResponseStartEvent,
@@ -50,9 +49,7 @@ def _get_status_line(status_code: int) -> bytes:
50
49
  return b"".join([b"HTTP/1.1 ", str(status_code).encode(), b" ", phrase, b"\r\n"])
51
50
 
52
51
 
53
- STATUS_LINE = {
54
- status_code: _get_status_line(status_code) for status_code in range(100, 600)
55
- }
52
+ STATUS_LINE = {status_code: _get_status_line(status_code) for status_code in range(100, 600)}
56
53
 
57
54
 
58
55
  class HttpToolsProtocol(asyncio.Protocol):
@@ -93,7 +90,7 @@ class HttpToolsProtocol(asyncio.Protocol):
93
90
  self.server: tuple[str, int] | None = None
94
91
  self.client: tuple[str, int] | None = None
95
92
  self.scheme: Literal["http", "https"] | None = None
96
- self.pipeline: Deque[tuple[RequestResponseCycle, ASGI3Application]] = deque()
93
+ self.pipeline: deque[tuple[RequestResponseCycle, ASGI3Application]] = deque()
97
94
 
98
95
  # Per-request state
99
96
  self.scope: HTTPScope = None # type: ignore[assignment]
@@ -227,7 +224,7 @@ class HttpToolsProtocol(asyncio.Protocol):
227
224
  self.headers = []
228
225
  self.scope = { # type: ignore[typeddict-item]
229
226
  "type": "http",
230
- "asgi": {"version": self.config.asgi_version, "spec_version": "2.3"},
227
+ "asgi": {"version": self.config.asgi_version, "spec_version": "2.4"},
231
228
  "http_version": "1.1",
232
229
  "server": self.server,
233
230
  "client": self.client,
@@ -268,8 +265,7 @@ class HttpToolsProtocol(asyncio.Protocol):
268
265
 
269
266
  # Handle 503 responses when 'limit_concurrency' is exceeded.
270
267
  if self.limit_concurrency is not None and (
271
- len(self.connections) >= self.limit_concurrency
272
- or len(self.tasks) >= self.limit_concurrency
268
+ len(self.connections) >= self.limit_concurrency or len(self.tasks) >= self.limit_concurrency
273
269
  ):
274
270
  app = service_unavailable
275
271
  message = "Exceeded concurrency limit."
@@ -302,9 +298,7 @@ class HttpToolsProtocol(asyncio.Protocol):
302
298
  self.pipeline.appendleft((self.cycle, app))
303
299
 
304
300
  def on_body(self, body: bytes) -> None:
305
- if (
306
- self.parser.should_upgrade() and self._should_upgrade()
307
- ) or self.cycle.response_complete:
301
+ if (self.parser.should_upgrade() and self._should_upgrade()) or self.cycle.response_complete:
308
302
  return
309
303
  self.cycle.body += body
310
304
  if len(self.cycle.body) > HIGH_WATER_LIMIT:
@@ -312,9 +306,7 @@ class HttpToolsProtocol(asyncio.Protocol):
312
306
  self.cycle.message_event.set()
313
307
 
314
308
  def on_message_complete(self) -> None:
315
- if (
316
- self.parser.should_upgrade() and self._should_upgrade()
317
- ) or self.cycle.response_complete:
309
+ if (self.parser.should_upgrade() and self._should_upgrade()) or self.cycle.response_complete:
318
310
  return
319
311
  self.cycle.more_body = False
320
312
  self.cycle.message_event.set()
@@ -376,7 +368,7 @@ class HttpToolsProtocol(asyncio.Protocol):
376
368
  class RequestResponseCycle:
377
369
  def __init__(
378
370
  self,
379
- scope: "HTTPScope",
371
+ scope: HTTPScope,
380
372
  transport: asyncio.Transport,
381
373
  flow: FlowControl,
382
374
  logger: logging.Logger,
@@ -414,7 +406,7 @@ class RequestResponseCycle:
414
406
  self.expected_content_length = 0
415
407
 
416
408
  # ASGI exception wrapper
417
- async def run_asgi(self, app: "ASGI3Application") -> None:
409
+ async def run_asgi(self, app: ASGI3Application) -> None:
418
410
  try:
419
411
  result = await app( # type: ignore[func-returns-value]
420
412
  self.scope, self.receive, self.send
@@ -443,7 +435,7 @@ class RequestResponseCycle:
443
435
  self.on_response = lambda: None
444
436
 
445
437
  async def send_500_response(self) -> None:
446
- response_start_event: "HTTPResponseStartEvent" = {
438
+ response_start_event: HTTPResponseStartEvent = {
447
439
  "type": "http.response.start",
448
440
  "status": 500,
449
441
  "headers": [
@@ -452,7 +444,7 @@ class RequestResponseCycle:
452
444
  ],
453
445
  }
454
446
  await self.send(response_start_event)
455
- response_body_event: "HTTPResponseBodyEvent" = {
447
+ response_body_event: HTTPResponseBodyEvent = {
456
448
  "type": "http.response.body",
457
449
  "body": b"Internal Server Error",
458
450
  "more_body": False,
@@ -460,7 +452,7 @@ class RequestResponseCycle:
460
452
  await self.send(response_body_event)
461
453
 
462
454
  # ASGI interface
463
- async def send(self, message: "ASGISendEvent") -> None:
455
+ async def send(self, message: ASGISendEvent) -> None:
464
456
  message_type = message["type"]
465
457
 
466
458
  if self.flow.write_paused and not self.disconnected:
@@ -515,11 +507,7 @@ class RequestResponseCycle:
515
507
  self.keep_alive = False
516
508
  content.extend([name, b": ", value, b"\r\n"])
517
509
 
518
- if (
519
- self.chunked_encoding is None
520
- and self.scope["method"] != "HEAD"
521
- and status_code not in (204, 304)
522
- ):
510
+ if self.chunked_encoding is None and self.scope["method"] != "HEAD" and status_code not in (204, 304):
523
511
  # Neither content-length nor transfer-encoding specified
524
512
  self.chunked_encoding = True
525
513
  content.append(b"transfer-encoding: chunked\r\n")
@@ -570,7 +558,7 @@ class RequestResponseCycle:
570
558
  msg = "Unexpected ASGI message '%s' sent, after response already completed."
571
559
  raise RuntimeError(msg % message_type)
572
560
 
573
- async def receive(self) -> "ASGIReceiveEvent":
561
+ async def receive(self) -> ASGIReceiveEvent:
574
562
  if self.waiting_for_100_continue and not self.transport.is_closing():
575
563
  self.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n")
576
564
  self.waiting_for_100_continue = False
@@ -580,15 +568,8 @@ class RequestResponseCycle:
580
568
  await self.message_event.wait()
581
569
  self.message_event.clear()
582
570
 
583
- message: HTTPDisconnectEvent | HTTPRequestEvent
584
571
  if self.disconnected or self.response_complete:
585
- message = {"type": "http.disconnect"}
586
- else:
587
- message = {
588
- "type": "http.request",
589
- "body": self.body,
590
- "more_body": self.more_body,
591
- }
592
- self.body = b""
593
-
572
+ return {"type": "http.disconnect"}
573
+ message: HTTPRequestEvent = {"type": "http.request", "body": self.body, "more_body": self.more_body}
574
+ self.body = b""
594
575
  return message
@@ -53,7 +53,5 @@ def get_client_addr(scope: WWWScope) -> str:
53
53
  def get_path_with_query_string(scope: WWWScope) -> str:
54
54
  path_with_query_string = urllib.parse.quote(scope["path"])
55
55
  if scope["query_string"]:
56
- path_with_query_string = "{}?{}".format(
57
- path_with_query_string, scope["query_string"].decode("ascii")
58
- )
56
+ path_with_query_string = "{}?{}".format(path_with_query_string, scope["query_string"].decode("ascii"))
59
57
  return path_with_query_string
@@ -1,7 +1,9 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import typing
3
5
 
4
- AutoWebSocketsProtocol: typing.Optional[typing.Callable[..., asyncio.Protocol]]
6
+ AutoWebSocketsProtocol: typing.Callable[..., asyncio.Protocol] | None
5
7
  try:
6
8
  import websockets # noqa
7
9
  except ImportError: # pragma: no cover
@@ -3,16 +3,7 @@ from __future__ import annotations
3
3
  import asyncio
4
4
  import http
5
5
  import logging
6
- from typing import (
7
- Any,
8
- List,
9
- Literal,
10
- Optional,
11
- Sequence,
12
- Tuple,
13
- Union,
14
- cast,
15
- )
6
+ from typing import Any, Literal, Optional, Sequence, cast
16
7
  from urllib.parse import unquote
17
8
 
18
9
  import websockets
@@ -61,7 +52,7 @@ class Server:
61
52
 
62
53
 
63
54
  class WebSocketProtocol(WebSocketServerProtocol):
64
- extra_headers: List[Tuple[str, str]]
55
+ extra_headers: list[tuple[str, str]]
65
56
 
66
57
  def __init__(
67
58
  self,
@@ -117,8 +108,7 @@ class WebSocketProtocol(WebSocketServerProtocol):
117
108
  )
118
109
  self.server_header = None
119
110
  self.extra_headers = [
120
- (name.decode("latin-1"), value.decode("latin-1"))
121
- for name, value in server_state.default_headers
111
+ (name.decode("latin-1"), value.decode("latin-1")) for name, value in server_state.default_headers
122
112
  ]
123
113
 
124
114
  def connection_made( # type: ignore[override]
@@ -136,16 +126,14 @@ class WebSocketProtocol(WebSocketServerProtocol):
136
126
 
137
127
  super().connection_made(transport)
138
128
 
139
- def connection_lost(self, exc: Optional[Exception]) -> None:
129
+ def connection_lost(self, exc: Exception | None) -> None:
140
130
  self.connections.remove(self)
141
131
 
142
132
  if self.logger.isEnabledFor(TRACE_LOG_LEVEL):
143
133
  prefix = "%s:%d - " % self.client if self.client else ""
144
134
  self.logger.log(TRACE_LOG_LEVEL, "%sWebSocket connection lost", prefix)
145
135
 
146
- self.lost_connection_before_handshake = (
147
- not self.handshake_completed_event.is_set()
148
- )
136
+ self.lost_connection_before_handshake = not self.handshake_completed_event.is_set()
149
137
  self.handshake_completed_event.set()
150
138
  super().connection_lost(exc)
151
139
  if exc is None:
@@ -162,9 +150,7 @@ class WebSocketProtocol(WebSocketServerProtocol):
162
150
  def on_task_complete(self, task: asyncio.Task) -> None:
163
151
  self.tasks.discard(task)
164
152
 
165
- async def process_request(
166
- self, path: str, headers: Headers
167
- ) -> Optional[HTTPResponse]:
153
+ async def process_request(self, path: str, headers: Headers) -> HTTPResponse | None:
168
154
  """
169
155
  This hook is called to determine if the websocket should return
170
156
  an HTTP response and close.
@@ -212,8 +198,8 @@ class WebSocketProtocol(WebSocketServerProtocol):
212
198
  return self.initial_response
213
199
 
214
200
  def process_subprotocol(
215
- self, headers: Headers, available_subprotocols: Optional[Sequence[Subprotocol]]
216
- ) -> Optional[Subprotocol]:
201
+ self, headers: Headers, available_subprotocols: Sequence[Subprotocol] | None
202
+ ) -> Subprotocol | None:
217
203
  """
218
204
  We override the standard 'process_subprotocol' behavior here so that
219
205
  we return whatever subprotocol is sent in the 'accept' message.
@@ -223,8 +209,7 @@ class WebSocketProtocol(WebSocketServerProtocol):
223
209
  def send_500_response(self) -> None:
224
210
  msg = b"Internal Server Error"
225
211
  content = [
226
- b"HTTP/1.1 500 Internal Server Error\r\n"
227
- b"content-type: text/plain; charset=utf-8\r\n",
212
+ b"HTTP/1.1 500 Internal Server Error\r\n" b"content-type: text/plain; charset=utf-8\r\n",
228
213
  b"content-length: " + str(len(msg)).encode("ascii") + b"\r\n",
229
214
  b"connection: close\r\n",
230
215
  b"\r\n",
@@ -278,7 +263,7 @@ class WebSocketProtocol(WebSocketServerProtocol):
278
263
  await self.handshake_completed_event.wait()
279
264
  self.transport.close()
280
265
 
281
- async def asgi_send(self, message: "ASGISendEvent") -> None:
266
+ async def asgi_send(self, message: ASGISendEvent) -> None:
282
267
  message_type = message["type"]
283
268
 
284
269
  if not self.handshake_started_event.is_set():
@@ -290,9 +275,7 @@ class WebSocketProtocol(WebSocketServerProtocol):
290
275
  get_path_with_query_string(self.scope),
291
276
  )
292
277
  self.initial_response = None
293
- self.accepted_subprotocol = cast(
294
- Optional[Subprotocol], message.get("subprotocol")
295
- )
278
+ self.accepted_subprotocol = cast(Optional[Subprotocol], message.get("subprotocol"))
296
279
  if "headers" in message:
297
280
  self.extra_headers.extend(
298
281
  # ASGI spec requires bytes
@@ -324,8 +307,7 @@ class WebSocketProtocol(WebSocketServerProtocol):
324
307
  # websockets requires the status to be an enum. look it up.
325
308
  status = http.HTTPStatus(message["status"])
326
309
  headers = [
327
- (name.decode("latin-1"), value.decode("latin-1"))
328
- for name, value in message.get("headers", [])
310
+ (name.decode("latin-1"), value.decode("latin-1")) for name, value in message.get("headers", [])
329
311
  ]
330
312
  self.initial_response = (status, headers, b"")
331
313
  self.handshake_started_event.set()
@@ -356,10 +338,7 @@ class WebSocketProtocol(WebSocketServerProtocol):
356
338
  self.closed_event.set()
357
339
 
358
340
  else:
359
- msg = (
360
- "Expected ASGI message 'websocket.send' or 'websocket.close',"
361
- " but got '%s'."
362
- )
341
+ msg = "Expected ASGI message 'websocket.send' or 'websocket.close'," " but got '%s'."
363
342
  raise RuntimeError(msg % message_type)
364
343
  except ConnectionClosed as exc:
365
344
  raise ClientDisconnected from exc
@@ -372,24 +351,16 @@ class WebSocketProtocol(WebSocketServerProtocol):
372
351
  if not message.get("more_body", False):
373
352
  self.closed_event.set()
374
353
  else:
375
- msg = (
376
- "Expected ASGI message 'websocket.http.response.body' "
377
- "but got '%s'."
378
- )
354
+ msg = "Expected ASGI message 'websocket.http.response.body' " "but got '%s'."
379
355
  raise RuntimeError(msg % message_type)
380
356
 
381
357
  else:
382
- msg = (
383
- "Unexpected ASGI message '%s', after sending 'websocket.close' "
384
- "or response already completed."
385
- )
358
+ msg = "Unexpected ASGI message '%s', after sending 'websocket.close' " "or response already completed."
386
359
  raise RuntimeError(msg % message_type)
387
360
 
388
361
  async def asgi_receive(
389
362
  self,
390
- ) -> Union[
391
- "WebSocketDisconnectEvent", "WebSocketConnectEvent", "WebSocketReceiveEvent"
392
- ]:
363
+ ) -> WebSocketDisconnectEvent | WebSocketConnectEvent | WebSocketReceiveEvent:
393
364
  if not self.connect_sent:
394
365
  self.connect_sent = True
395
366
  return {"type": "websocket.connect"}
@@ -168,7 +168,7 @@ class WSProtocol(asyncio.Protocol):
168
168
  path = unquote(raw_path)
169
169
  full_path = self.root_path + path
170
170
  full_raw_path = self.root_path.encode("ascii") + raw_path.encode("ascii")
171
- self.scope: "WebSocketScope" = {
171
+ self.scope: WebSocketScope = {
172
172
  "type": "websocket",
173
173
  "asgi": {"version": self.config.asgi_version, "spec_version": "2.4"},
174
174
  "http_version": "1.1",
@@ -224,14 +224,8 @@ class WSProtocol(asyncio.Protocol):
224
224
  (b"content-type", b"text/plain; charset=utf-8"),
225
225
  (b"connection", b"close"),
226
226
  ]
227
- output = self.conn.send(
228
- wsproto.events.RejectConnection(
229
- status_code=500, headers=headers, has_body=True
230
- )
231
- )
232
- output += self.conn.send(
233
- wsproto.events.RejectData(data=b"Internal Server Error")
234
- )
227
+ output = self.conn.send(wsproto.events.RejectConnection(status_code=500, headers=headers, has_body=True))
228
+ output += self.conn.send(wsproto.events.RejectData(data=b"Internal Server Error"))
235
229
  self.transport.write(output)
236
230
 
237
231
  async def run_asgi(self) -> None:
@@ -269,7 +263,7 @@ class WSProtocol(asyncio.Protocol):
269
263
  )
270
264
  subprotocol = message.get("subprotocol")
271
265
  extra_headers = self.default_headers + list(message.get("headers", []))
272
- extensions: typing.List[Extension] = []
266
+ extensions: list[Extension] = []
273
267
  if self.config.ws_per_message_deflate:
274
268
  extensions.append(PerMessageDeflate())
275
269
  if not self.transport.is_closing():
@@ -343,21 +337,14 @@ class WSProtocol(asyncio.Protocol):
343
337
  self.close_sent = True
344
338
  code = message.get("code", 1000)
345
339
  reason = message.get("reason", "") or ""
346
- self.queue.put_nowait(
347
- {"type": "websocket.disconnect", "code": code}
348
- )
349
- output = self.conn.send(
350
- wsproto.events.CloseConnection(code=code, reason=reason)
351
- )
340
+ self.queue.put_nowait({"type": "websocket.disconnect", "code": code})
341
+ output = self.conn.send(wsproto.events.CloseConnection(code=code, reason=reason))
352
342
  if not self.transport.is_closing():
353
343
  self.transport.write(output)
354
344
  self.transport.close()
355
345
 
356
346
  else:
357
- msg = (
358
- "Expected ASGI message 'websocket.send' or 'websocket.close',"
359
- " but got '%s'."
360
- )
347
+ msg = "Expected ASGI message 'websocket.send' or 'websocket.close'," " but got '%s'."
361
348
  raise RuntimeError(msg % message_type)
362
349
  except LocalProtocolError as exc:
363
350
  raise ClientDisconnected from exc
@@ -365,24 +352,17 @@ class WSProtocol(asyncio.Protocol):
365
352
  if message_type == "websocket.http.response.body":
366
353
  message = typing.cast("WebSocketResponseBodyEvent", message)
367
354
  body_finished = not message.get("more_body", False)
368
- reject_data = events.RejectData(
369
- data=message["body"], body_finished=body_finished
370
- )
355
+ reject_data = events.RejectData(data=message["body"], body_finished=body_finished)
371
356
  output = self.conn.send(reject_data)
372
357
  self.transport.write(output)
373
358
 
374
359
  if body_finished:
375
- self.queue.put_nowait(
376
- {"type": "websocket.disconnect", "code": 1006}
377
- )
360
+ self.queue.put_nowait({"type": "websocket.disconnect", "code": 1006})
378
361
  self.close_sent = True
379
362
  self.transport.close()
380
363
 
381
364
  else:
382
- msg = (
383
- "Expected ASGI message 'websocket.http.response.body' "
384
- "but got '%s'."
385
- )
365
+ msg = "Expected ASGI message 'websocket.http.response.body' " "but got '%s'."
386
366
  raise RuntimeError(msg % message_type)
387
367
 
388
368
  else:
uvicorn/server.py CHANGED
@@ -126,18 +126,14 @@ class Server:
126
126
  is_windows = platform.system() == "Windows"
127
127
  if config.workers > 1 and is_windows: # pragma: py-not-win32
128
128
  sock = _share_socket(sock) # type: ignore[assignment]
129
- server = await loop.create_server(
130
- create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog
131
- )
129
+ server = await loop.create_server(create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog)
132
130
  self.servers.append(server)
133
131
  listeners = sockets
134
132
 
135
133
  elif config.fd is not None: # pragma: py-win32
136
134
  # Use an existing socket, from a file descriptor.
137
135
  sock = socket.fromfd(config.fd, socket.AF_UNIX, socket.SOCK_STREAM)
138
- server = await loop.create_server(
139
- create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog
140
- )
136
+ server = await loop.create_server(create_protocol, sock=sock, ssl=config.ssl, backlog=config.backlog)
141
137
  assert server.sockets is not None # mypy
142
138
  listeners = server.sockets
143
139
  self.servers = [server]
@@ -194,9 +190,7 @@ class Server:
194
190
  )
195
191
 
196
192
  elif config.uds is not None: # pragma: py-win32
197
- logger.info(
198
- "Uvicorn running on unix socket %s (Press CTRL+C to quit)", config.uds
199
- )
193
+ logger.info("Uvicorn running on unix socket %s (Press CTRL+C to quit)", config.uds)
200
194
 
201
195
  else:
202
196
  addr_format = "%s://%s:%d"
@@ -211,11 +205,7 @@ class Server:
211
205
 
212
206
  protocol_name = "https" if config.ssl else "http"
213
207
  message = f"Uvicorn running on {addr_format} (Press CTRL+C to quit)"
214
- color_message = (
215
- "Uvicorn running on "
216
- + click.style(addr_format, bold=True)
217
- + " (Press CTRL+C to quit)"
218
- )
208
+ color_message = "Uvicorn running on " + click.style(addr_format, bold=True) + " (Press CTRL+C to quit)"
219
209
  logger.info(
220
210
  message,
221
211
  protocol_name,
@@ -244,9 +234,7 @@ class Server:
244
234
  else:
245
235
  date_header = []
246
236
 
247
- self.server_state.default_headers = (
248
- date_header + self.config.encoded_headers
249
- )
237
+ self.server_state.default_headers = date_header + self.config.encoded_headers
250
238
 
251
239
  # Callback to `callback_notify` once every `timeout_notify` seconds.
252
240
  if self.config.callback_notify is not None:
@@ -1,10 +1,12 @@
1
- from typing import TYPE_CHECKING, Type
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
2
4
 
3
5
  from uvicorn.supervisors.basereload import BaseReload
4
6
  from uvicorn.supervisors.multiprocess import Multiprocess
5
7
 
6
8
  if TYPE_CHECKING:
7
- ChangeReload: Type[BaseReload]
9
+ ChangeReload: type[BaseReload]
8
10
  else:
9
11
  try:
10
12
  from uvicorn.supervisors.watchfilesreload import (
@@ -81,9 +81,7 @@ class BaseReload:
81
81
  for sig in HANDLED_SIGNALS:
82
82
  signal.signal(sig, self.signal_handler)
83
83
 
84
- self.process = get_subprocess(
85
- config=self.config, target=self.target, sockets=self.sockets
86
- )
84
+ self.process = get_subprocess(config=self.config, target=self.target, sockets=self.sockets)
87
85
  self.process.start()
88
86
 
89
87
  def restart(self) -> None:
@@ -95,9 +93,7 @@ class BaseReload:
95
93
  self.process.terminate()
96
94
  self.process.join()
97
95
 
98
- self.process = get_subprocess(
99
- config=self.config, target=self.target, sockets=self.sockets
100
- )
96
+ self.process = get_subprocess(config=self.config, target=self.target, sockets=self.sockets)
101
97
  self.process.start()
102
98
 
103
99
  def shutdown(self) -> None:
@@ -110,10 +106,8 @@ class BaseReload:
110
106
  for sock in self.sockets:
111
107
  sock.close()
112
108
 
113
- message = "Stopping reloader process [{}]".format(str(self.pid))
114
- color_message = "Stopping reloader process [{}]".format(
115
- click.style(str(self.pid), fg="cyan", bold=True)
116
- )
109
+ message = f"Stopping reloader process [{str(self.pid)}]"
110
+ color_message = "Stopping reloader process [{}]".format(click.style(str(self.pid), fg="cyan", bold=True))
117
111
  logger.info(message, extra={"color_message": color_message})
118
112
 
119
113
  def should_restart(self) -> list[Path] | None:
@@ -48,19 +48,15 @@ class Multiprocess:
48
48
  self.shutdown()
49
49
 
50
50
  def startup(self) -> None:
51
- message = "Started parent process [{}]".format(str(self.pid))
52
- color_message = "Started parent process [{}]".format(
53
- click.style(str(self.pid), fg="cyan", bold=True)
54
- )
51
+ message = f"Started parent process [{str(self.pid)}]"
52
+ color_message = "Started parent process [{}]".format(click.style(str(self.pid), fg="cyan", bold=True))
55
53
  logger.info(message, extra={"color_message": color_message})
56
54
 
57
55
  for sig in HANDLED_SIGNALS:
58
56
  signal.signal(sig, self.signal_handler)
59
57
 
60
58
  for _idx in range(self.config.workers):
61
- process = get_subprocess(
62
- config=self.config, target=self.target, sockets=self.sockets
63
- )
59
+ process = get_subprocess(config=self.config, target=self.target, sockets=self.sockets)
64
60
  process.start()
65
61
  self.processes.append(process)
66
62
 
@@ -69,8 +65,6 @@ class Multiprocess:
69
65
  process.terminate()
70
66
  process.join()
71
67
 
72
- message = "Stopping parent process [{}]".format(str(self.pid))
73
- color_message = "Stopping parent process [{}]".format(
74
- click.style(str(self.pid), fg="cyan", bold=True)
75
- )
68
+ message = f"Stopping parent process [{str(self.pid)}]"
69
+ color_message = "Stopping parent process [{}]".format(click.style(str(self.pid), fg="cyan", bold=True))
76
70
  logger.info(message, extra={"color_message": color_message})