Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make Function an ASGI callable #9

Merged
merged 1 commit into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions cmd/fhttp/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,28 @@
import logging
from func_python.http import serve

# Set the default logging level to INFO
logging.basicConfig(level=logging.INFO)

# Allow this test to be either instanced (default) or --static
# to test the two different primary method signatures supported in the
# final Function.
parser = argparse.ArgumentParser(description='Serve a Test Function')
parser.add_argument('--static', action='store_true',
help='Serve the example static handler (default is to '
'instantiate and serve the example class)')
args = parser.parse_args()


# Example static handler.
# Enable with --static
# Must be named exactly "handle"
async def handle(scope, receive, send):
""" handle is an example of a static handler which can be sent to the
middleware as a funciton. It will be wrapped in a default Funciton
instance before being served as an ASGI application.
"""
logging.info("OK: static")
logging.info("OK: static!!")

await send({
'type': 'http.response.start',
Expand All @@ -29,17 +36,19 @@ async def handle(scope, receive, send):
})


class Function:
# Example instanced handler
# This is the default expected by this test.
# The class can be named anything. See "new" below.
class MyFunction:
""" Function is an example of a functioon instance. The structure
implements the function which will be deployed as a network service.
The class name can be changed. The only required method is "handle".
"""

async def handle(self, scope, receive, send):
async def __call__(self, scope, receive, send):
""" handle is the only method which must be implemented by the
function instance for it to be served as an ASGI handler.
"""
logging.info("OK: instanced")
logging.info("OK: instanced!!")

await send({
'type': 'http.response.start',
Expand All @@ -52,16 +61,21 @@ async def handle(self, scope, receive, send):
})


# Funciton instance constructor
# expected to be named exactly "new"
# Must return a callable which conforms to the ASGI spec.
def new():
""" new is the factory function (or constructor) which will create
a new function instance when invoked. This must be named "new", and the
structure returned must include a method named "handle" which implements
the ASGI specification's method signature. The name of the class itself
can be changed.
"""
return Function()
return MyFunction()


# Run the example.
# Start either the static or instanced handler depending on flag --static
if __name__ == "__main__":
if args.static:
logging.info("Starting static handler")
Expand Down
8 changes: 6 additions & 2 deletions src/func_python/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class DefaultFunction:
def __init__(self, handler):
self.handle = handler

async def __call__(self, scope, receive, send):
# delegate to the handler implementation provided during construction.
await self.handle (scope, receive, send)


class ASGIApplication():
def __init__(self, f):
Expand Down Expand Up @@ -105,8 +109,8 @@ async def __call__(self, scope, receive, send):
elif scope['path'] == '/health/readiness':
await self.handle_readiness(scope, receive, send)
else:
if hasattr(self.f, "handle"):
await self.f.handle(scope, receive, send)
if callable(self.f):
await self.f(scope, receive, send)
else:
raise Exception("function does not implement handle")
except Exception as e:
Expand Down
Loading