@vercel/python 3.1.0 → 3.1.3

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 (2) hide show
  1. package/package.json +3 -3
  2. package/vc_init.py +7 -171
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/python",
3
- "version": "3.1.0",
3
+ "version": "3.1.3",
4
4
  "main": "./dist/index.js",
5
5
  "license": "MIT",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -23,10 +23,10 @@
23
23
  "devDependencies": {
24
24
  "@types/execa": "^0.9.0",
25
25
  "@types/jest": "27.4.1",
26
- "@vercel/build-utils": "5.0.4",
26
+ "@vercel/build-utils": "5.0.7",
27
27
  "@vercel/ncc": "0.24.0",
28
28
  "execa": "^1.0.0",
29
29
  "typescript": "4.3.4"
30
30
  },
31
- "gitHead": "3d3774ee7e3d344b3292d2166d485bdf41a68d4c"
31
+ "gitHead": "e8c7db59cf2746422f1f7e14cc6b7f901c243d50"
32
32
  }
package/vc_init.py CHANGED
@@ -167,23 +167,13 @@ elif 'app' in __vc_variables:
167
167
  else:
168
168
  print('using Asynchronous Server Gateway Interface (ASGI)')
169
169
  # Originally authored by Jordan Eremieff and included under MIT license:
170
- # https://github.com/erm/mangum/blob/07ce20a0e2f67c5c2593258a92c03fdc66d9edda/mangum/__init__.py
171
- # https://github.com/erm/mangum/blob/07ce20a0e2f67c5c2593258a92c03fdc66d9edda/LICENSE
170
+ # https://github.com/erm/mangum/blob/b4d21c8f5e304a3e17b88bc9fa345106acc50ad7/mangum/__init__.py
171
+ # https://github.com/erm/mangum/blob/b4d21c8f5e304a3e17b88bc9fa345106acc50ad7/LICENSE
172
172
  import asyncio
173
173
  import enum
174
- import logging
175
- from contextlib import ExitStack
176
174
  from urllib.parse import urlparse
177
175
  from werkzeug.datastructures import Headers
178
176
 
179
- def get_event_loop():
180
- try:
181
- return asyncio.get_running_loop()
182
- except:
183
- if sys.version_info < (3, 10):
184
- return asyncio.get_event_loop()
185
- else:
186
- return asyncio.get_event_loop_policy().get_event_loop()
187
177
 
188
178
  class ASGICycleState(enum.Enum):
189
179
  REQUEST = enum.auto()
@@ -204,8 +194,8 @@ elif 'app' in __vc_variables:
204
194
  ASGI instance using the connection scope.
205
195
  Runs until the response is completely read from the application.
206
196
  """
207
- loop = get_event_loop()
208
- self.app_queue = asyncio.Queue()
197
+ loop = asyncio.new_event_loop()
198
+ self.app_queue = asyncio.Queue(loop=loop)
209
199
  self.put_message({'type': 'http.request', 'body': body, 'more_body': False})
210
200
 
211
201
  asgi_instance = app(self.scope, self.receive, self.send)
@@ -267,156 +257,6 @@ elif 'app' in __vc_variables:
267
257
  self.response['body'] = base64.b64encode(self.body).decode('utf-8')
268
258
  self.response['encoding'] = 'base64'
269
259
 
270
- class LifespanFailure(Exception):
271
- """Raise when a lifespan failure event is sent by an application."""
272
-
273
- class LifespanUnsupported(Exception):
274
- """Raise when lifespan events are not supported by an application."""
275
-
276
- class UnexpectedMessage(Exception):
277
- """Raise when an unexpected message type is received during an ASGI cycle."""
278
-
279
- class LifespanCycleState(enum.Enum):
280
- """
281
- The state of the ASGI `lifespan` connection.
282
- * **CONNECTING** - Initial state. The ASGI application instance will be run with
283
- the connection scope containing the `lifespan` type.
284
- * **STARTUP** - The lifespan startup event has been pushed to the queue to be
285
- received by the application.
286
- * **SHUTDOWN** - The lifespan shutdown event has been pushed to the queue to be
287
- received by the application.
288
- * **FAILED** - A lifespan failure has been detected, and the connection will be
289
- closed with an error.
290
- * **UNSUPPORTED** - An application attempted to send a message before receiving
291
- the lifepan startup event. If the lifespan argument is "on", then the connection
292
- will be closed with an error.
293
- """
294
-
295
- CONNECTING = enum.auto()
296
- STARTUP = enum.auto()
297
- SHUTDOWN = enum.auto()
298
- FAILED = enum.auto()
299
- UNSUPPORTED = enum.auto()
300
-
301
- class Lifespan:
302
-
303
- def __init__(self, app):
304
- self.app = app
305
- self.state = LifespanCycleState.CONNECTING
306
- self.exception = None
307
- self.logger = logging.getLogger('lifespan')
308
- self.loop = get_event_loop()
309
- self.app_queue = asyncio.Queue()
310
- self.startup_event = asyncio.Event()
311
- self.shutdown_event = asyncio.Event()
312
-
313
-
314
- def __enter__(self) -> None:
315
- """Runs the event loop for application startup."""
316
- self.loop.create_task(self.run())
317
- self.loop.run_until_complete(self.startup())
318
-
319
- def __exit__(
320
- self,
321
- exc_type,
322
- exc_value,
323
- traceback,
324
- ) -> None:
325
- """Runs the event loop for application shutdown."""
326
- self.loop.run_until_complete(self.shutdown())
327
-
328
- async def run(self):
329
- """Calls the application with the `lifespan` connection scope."""
330
- try:
331
- await self.app(
332
- {"type": "lifespan", "asgi": {"spec_version": "2.0", "version": "3.0"}},
333
- self.receive,
334
- self.send,
335
- )
336
- except LifespanUnsupported:
337
- self.logger.info("ASGI 'lifespan' protocol appears unsupported.")
338
- except (LifespanFailure, UnexpectedMessage) as exc:
339
- self.exception = exc
340
- except BaseException as exc:
341
- self.logger.error("Exception in 'lifespan' protocol.", exc_info=exc)
342
- finally:
343
- self.startup_event.set()
344
- self.shutdown_event.set()
345
-
346
- async def send(self, message):
347
- """Awaited by the application to send ASGI `lifespan` events."""
348
- message_type = message["type"]
349
-
350
- if self.state is LifespanCycleState.CONNECTING:
351
- # If a message is sent before the startup event is received by the
352
- # application, then assume that lifespan is unsupported.
353
- self.state = LifespanCycleState.UNSUPPORTED
354
- raise LifespanUnsupported("Lifespan protocol appears unsupported.")
355
-
356
- if message_type not in (
357
- "lifespan.startup.complete",
358
- "lifespan.shutdown.complete",
359
- "lifespan.startup.failed",
360
- "lifespan.shutdown.failed",
361
- ):
362
- self.state = LifespanCycleState.FAILED
363
- raise UnexpectedMessage(f"Unexpected '{message_type}' event received.")
364
-
365
- if self.state is LifespanCycleState.STARTUP:
366
- if message_type == "lifespan.startup.complete":
367
- self.startup_event.set()
368
- elif message_type == "lifespan.startup.failed":
369
- self.state = LifespanCycleState.FAILED
370
- self.startup_event.set()
371
- message_value = message.get("message", "")
372
- raise LifespanFailure(f"Lifespan startup failure. {message_value}")
373
-
374
- elif self.state is LifespanCycleState.SHUTDOWN:
375
- if message_type == "lifespan.shutdown.complete":
376
- self.shutdown_event.set()
377
- elif message_type == "lifespan.shutdown.failed":
378
- self.state = LifespanCycleState.FAILED
379
- self.shutdown_event.set()
380
- message_value = message.get("message", "")
381
- raise LifespanFailure(f"Lifespan shutdown failure. {message_value}")
382
-
383
- async def receive(self):
384
- """Awaited by the application to receive ASGI `lifespan` events."""
385
- if self.state is LifespanCycleState.CONNECTING:
386
-
387
- # Connection established. The next event returned by the queue will be
388
- # `lifespan.startup` to inform the application that the connection is
389
- # ready to receive lfiespan messages.
390
- self.state = LifespanCycleState.STARTUP
391
-
392
- elif self.state is LifespanCycleState.STARTUP:
393
-
394
- # Connection shutting down. The next event returned by the queue will be
395
- # `lifespan.shutdown` to inform the application that the connection is now
396
- # closing so that it may perform cleanup.
397
- self.state = LifespanCycleState.SHUTDOWN
398
-
399
- return await self.app_queue.get()
400
-
401
- async def startup(self) -> None:
402
- """Pushes the `lifespan` startup event to the queue and handles errors."""
403
- await self.app_queue.put({"type": "lifespan.startup"})
404
- await self.startup_event.wait()
405
- if self.state is LifespanCycleState.FAILED:
406
- raise LifespanFailure(self.exception)
407
-
408
- if not self.exception:
409
- self.logger.info("Application startup complete.")
410
- else:
411
- self.logger.info("Application startup failed.")
412
-
413
- async def shutdown(self) -> None:
414
- """Pushes the `lifespan` shutdown event to the queue and handles errors."""
415
- await self.app_queue.put({"type": "lifespan.shutdown"})
416
- await self.shutdown_event.wait()
417
- if self.state is LifespanCycleState.FAILED:
418
- raise LifespanFailure(self.exception)
419
-
420
260
  def vc_handler(event, context):
421
261
  payload = json.loads(event['body'])
422
262
 
@@ -449,13 +289,9 @@ elif 'app' in __vc_variables:
449
289
  'raw_path': path.encode(),
450
290
  }
451
291
 
452
- with ExitStack() as stack:
453
- lifespan = Lifespan(__vc_module.app)
454
- stack.enter_context(lifespan)
455
-
456
- asgi_cycle = ASGICycle(scope)
457
- response = asgi_cycle(__vc_module.app, body)
458
- return response
292
+ asgi_cycle = ASGICycle(scope)
293
+ response = asgi_cycle(__vc_module.app, body)
294
+ return response
459
295
 
460
296
  else:
461
297
  print('Missing variable `handler` or `app` in file "__VC_HANDLER_ENTRYPOINT".')