From a132253cb1a8e9a400da9c8d269405e21f2cd66e Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 18 Dec 2024 15:09:16 -0600 Subject: [PATCH] feat: add basic support for running in ASGI context --- pyproject.toml | 1 + src/wuttaweb/app.py | 14 ++++++++++++++ tests/test_app.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 6a2d965..f5c65db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ classifiers = [ ] requires-python = ">= 3.8" dependencies = [ + "asgiref", "ColanderAlchemy", "humanize", "markdown", diff --git a/src/wuttaweb/app.py b/src/wuttaweb/app.py index 912a5d1..63def58 100644 --- a/src/wuttaweb/app.py +++ b/src/wuttaweb/app.py @@ -30,6 +30,7 @@ import os from wuttjamaican.app import AppProvider from wuttjamaican.conf import make_config +from asgiref.wsgi import WsgiToAsgi from pyramid.config import Configurator import wuttaweb.db @@ -182,6 +183,8 @@ def make_wsgi_app(main_app=None, config=None): """ Make and return a WSGI app, using the given Paste app factory. + See also :func:`make_asgi_app()` for the ASGI equivalent. + This function could be used directly for general WSGI servers (e.g. uvicorn), ***if*** you just want the built-in :func:`main()` app factory. @@ -231,3 +234,14 @@ def make_wsgi_app(main_app=None, config=None): # construct a pyramid app "per usual" return make_wsgi_app({}, **settings) + + +def make_asgi_app(main_app=None, config=None): + """ + Make and return a ASGI app, using the given Paste app factory. + + This works the same as :func:`make_wsgi_app()` and should be + called in the same way etc. + """ + wsgi_app = make_wsgi_app(main_app, config=config) + return WsgiToAsgi(wsgi_app) diff --git a/tests/test_app.py b/tests/test_app.py index a38d5e6..8b092d8 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -5,6 +5,7 @@ from unittest.mock import patch from wuttjamaican.testing import FileTestCase, ConfigTestCase +from asgiref.wsgi import WsgiToAsgi from pyramid.config import Configurator from pyramid.router import Router @@ -100,3 +101,31 @@ class TestMakeWsgiApp(ConfigTestCase): def test_invalid(self): self.assertRaises(ValueError, mod.make_wsgi_app, 42, config=self.config) + + +class TestMakeAsgiApp(ConfigTestCase): + + def test_with_callable(self): + + # specify config + asgi = mod.make_asgi_app(mock_main, config=self.config) + self.assertIsInstance(asgi, WsgiToAsgi) + + # auto config + with patch.object(mod, 'make_config', return_value=self.config): + asgi = mod.make_asgi_app(mock_main) + self.assertIsInstance(asgi, WsgiToAsgi) + + def test_with_spec(self): + + # specify config + asgi = mod.make_asgi_app('tests.test_app:mock_main', config=self.config) + self.assertIsInstance(asgi, WsgiToAsgi) + + # auto config + with patch.object(mod, 'make_config', return_value=self.config): + asgi = mod.make_asgi_app('tests.test_app:mock_main') + self.assertIsInstance(asgi, WsgiToAsgi) + + def test_invalid(self): + self.assertRaises(ValueError, mod.make_asgi_app, 42, config=self.config)