@@ -199,8 +199,7 @@ nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto)
199
199
200
200
return NXT_UNIT_OK ;
201
201
}
202
-
203
-
202
+ #if NXT_HAVE_ASYNCIO_RUNNER
204
203
static int
205
204
nxt_python_asgi_ctx_data_alloc (void * * pdata , int main )
206
205
{
@@ -346,6 +345,150 @@ nxt_python_asgi_ctx_data_free(void *data)
346
345
347
346
nxt_unit_free (NULL , ctx_data );
348
347
}
348
+ #else
349
+
350
+ static int
351
+ nxt_python_asgi_ctx_data_alloc (void * * pdata , int main )
352
+ {
353
+ uint32_t i ;
354
+ PyObject * asyncio , * loop , * event_loop , * obj ;
355
+ const char * event_loop_func ;
356
+ nxt_py_asgi_ctx_data_t * ctx_data ;
357
+
358
+ ctx_data = nxt_unit_malloc (NULL , sizeof (nxt_py_asgi_ctx_data_t ));
359
+ if (nxt_slow_path (ctx_data == NULL )) {
360
+ nxt_unit_alert (NULL , "Failed to allocate context data" );
361
+ return NXT_UNIT_ERROR ;
362
+ }
363
+
364
+ memset (ctx_data , 0 , sizeof (nxt_py_asgi_ctx_data_t ));
365
+
366
+ nxt_queue_init (& ctx_data -> drain_queue );
367
+
368
+ struct {
369
+ const char * key ;
370
+ PyObject * * handler ;
371
+
372
+ } handlers [] = {
373
+ { "create_task" , & ctx_data -> loop_create_task },
374
+ { "add_reader" , & ctx_data -> loop_add_reader },
375
+ { "remove_reader" , & ctx_data -> loop_remove_reader },
376
+ { "call_soon" , & ctx_data -> loop_call_soon },
377
+ { "run_until_complete" , & ctx_data -> loop_run_until_complete },
378
+ { "create_future" , & ctx_data -> loop_create_future },
379
+ };
380
+
381
+ loop = NULL ;
382
+
383
+ asyncio = PyImport_ImportModule ("asyncio" );
384
+ if (nxt_slow_path (asyncio == NULL )) {
385
+ nxt_unit_alert (NULL , "Python failed to import module 'asyncio'" );
386
+ nxt_python_print_exception ();
387
+ goto fail ;
388
+ }
389
+
390
+ event_loop_func = main ? "get_event_loop" : "new_event_loop" ;
391
+
392
+ event_loop = PyDict_GetItemString (PyModule_GetDict (asyncio ),
393
+ event_loop_func );
394
+ if (nxt_slow_path (event_loop == NULL )) {
395
+ nxt_unit_alert (NULL ,
396
+ "Python failed to get '%s' from module 'asyncio'" ,
397
+ event_loop_func );
398
+ goto fail ;
399
+ }
400
+
401
+ if (nxt_slow_path (PyCallable_Check (event_loop ) == 0 )) {
402
+ nxt_unit_alert (NULL ,
403
+ "'asyncio.%s' is not a callable object" ,
404
+ event_loop_func );
405
+ goto fail ;
406
+ }
407
+
408
+ loop = PyObject_CallObject (event_loop , NULL );
409
+ if (nxt_slow_path (loop == NULL )) {
410
+ nxt_unit_alert (NULL , "Python failed to call 'asyncio.%s'" ,
411
+ event_loop_func );
412
+ goto fail ;
413
+ }
414
+
415
+ for (i = 0 ; i < nxt_nitems (handlers ); i ++ ) {
416
+ obj = PyObject_GetAttrString (loop , handlers [i ].key );
417
+ if (nxt_slow_path (obj == NULL )) {
418
+ nxt_unit_alert (NULL , "Python failed to get 'loop.%s'" ,
419
+ handlers [i ].key );
420
+ goto fail ;
421
+ }
422
+
423
+ * handlers [i ].handler = obj ;
424
+
425
+ if (nxt_slow_path (PyCallable_Check (obj ) == 0 )) {
426
+ nxt_unit_alert (NULL , "'loop.%s' is not a callable object" ,
427
+ handlers [i ].key );
428
+ goto fail ;
429
+ }
430
+ }
431
+
432
+ obj = PyObject_CallObject (ctx_data -> loop_create_future , NULL );
433
+ if (nxt_slow_path (obj == NULL )) {
434
+ nxt_unit_alert (NULL , "Python failed to create Future " );
435
+ nxt_python_print_exception ();
436
+ goto fail ;
437
+ }
438
+
439
+ ctx_data -> quit_future = obj ;
440
+
441
+ obj = PyObject_GetAttrString (ctx_data -> quit_future , "set_result" );
442
+ if (nxt_slow_path (obj == NULL )) {
443
+ nxt_unit_alert (NULL , "Python failed to get 'future.set_result'" );
444
+ goto fail ;
445
+ }
446
+
447
+ ctx_data -> quit_future_set_result = obj ;
448
+
449
+ if (nxt_slow_path (PyCallable_Check (obj ) == 0 )) {
450
+ nxt_unit_alert (NULL , "'future.set_result' is not a callable object" );
451
+ goto fail ;
452
+ }
453
+
454
+ Py_DECREF (loop );
455
+ Py_DECREF (asyncio );
456
+
457
+ * pdata = ctx_data ;
458
+
459
+ return NXT_UNIT_OK ;
460
+
461
+ fail :
462
+
463
+ nxt_python_asgi_ctx_data_free (ctx_data );
464
+
465
+ Py_XDECREF (loop );
466
+ Py_XDECREF (asyncio );
467
+
468
+ return NXT_UNIT_ERROR ;
469
+ }
470
+
471
+
472
+ static void
473
+ nxt_python_asgi_ctx_data_free (void * data )
474
+ {
475
+ nxt_py_asgi_ctx_data_t * ctx_data ;
476
+
477
+ ctx_data = data ;
478
+
479
+ Py_XDECREF (ctx_data -> loop_run_until_complete );
480
+ Py_XDECREF (ctx_data -> loop_create_future );
481
+ Py_XDECREF (ctx_data -> loop_create_task );
482
+ Py_XDECREF (ctx_data -> loop_call_soon );
483
+ Py_XDECREF (ctx_data -> loop_add_reader );
484
+ Py_XDECREF (ctx_data -> loop_remove_reader );
485
+ Py_XDECREF (ctx_data -> quit_future );
486
+ Py_XDECREF (ctx_data -> quit_future_set_result );
487
+
488
+ nxt_unit_free (NULL , ctx_data );
489
+ }
490
+ #endif
491
+
349
492
350
493
351
494
static int
0 commit comments