Compare commits

..

13 Commits

Author SHA1 Message Date
kennethreitz dd0ddab610 single page 2018-10-17 04:52:02 -07:00
kennethreitz d23ac10f90 version 2018-10-17 04:49:00 -07:00
kennethreitz ec18290b8a changelog 2018-10-17 04:48:38 -07:00
kennethreitz 2c4cd39dc9 static application support 2018-10-17 04:48:33 -07:00
kennethreitz 830bad0b85 docs for #53 2018-10-17 04:47:39 -07:00
kennethreitz f14ef6fa15 #53 2018-10-17 04:45:12 -07:00
kennethreitz 7400b1c83d static support #53 2018-10-17 04:38:51 -07:00
kennethreitz e7caf39fba static_route 2018-10-17 04:25:09 -07:00
kennethreitz 09fd0fb0ca version 2018-10-17 04:19:38 -07:00
kennethreitz 72adb13c0f version 2018-10-17 04:16:22 -07:00
kennethreitz ea0e382f82 test for #71 2018-10-17 04:15:36 -07:00
kennethreitz e70cba5143 Fix for #71 2018-10-17 04:12:13 -07:00
kennethreitz 8aec244c31 openapi 2018-10-17 04:12:03 -07:00
7 changed files with 54 additions and 10 deletions
+9
View File
@@ -1,3 +1,12 @@
# v0.1.0
- Prototype of static application support.
# v0.0.10
- Bufgix for async class-based views.
# v0.0.9
- Bugfix for async class-based views.
# v0.0.8
- GraphiQL Support.
- Improvement to route selection.
+2
View File
@@ -55,6 +55,8 @@ Features
- Mutable response object, passed into each view. No need to return anything.
- Background tasks, spawned off in a ``ThreadPoolExecutor``.
- GraphQL (with *GraphiQL*) support!
- OpenAPI schema generation.
- Single-page webapp support!
Testimonials
------------
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.0.8"
__version__ = "0.1.0"
+30 -9
View File
@@ -42,6 +42,7 @@ class API:
openapi=None,
openapi_route="/schema.yml",
static_dir="static",
static_route="/static",
templates_dir="templates",
enable_hsts=False,
):
@@ -49,7 +50,7 @@ class API:
self.version = version
self.openapi_version = openapi
self.static_dir = Path(os.path.abspath(static_dir))
self.static_route = f"/{static_dir}"
self.static_route = static_route
self.templates_dir = Path(os.path.abspath(templates_dir))
self.built_in_templates_dir = Path(
os.path.abspath(os.path.dirname(__file__) + "/templates")
@@ -74,6 +75,8 @@ class API:
if self.openapi_version:
self.add_route(openapi_route, self.schema_response)
self.static_enabled = False
@property
def _apispec(self):
spec = APISpec(
@@ -198,15 +201,19 @@ class API:
# Run on_request first.
try:
getattr(view, "on_request")(req, resp)
r = getattr(view, "on_request")(req, resp)
if hasattr(r, "send"):
await r
except AttributeError:
pass
# Then on_get.
method = req.method.lower()
method = req.method
try:
getattr(view, f"on_{method}")(req, resp)
r = getattr(view, f"on_{method}")(req, resp)
if hasattr(r, "send"):
await r
except AttributeError:
pass
else:
@@ -214,15 +221,20 @@ class API:
return resp
def add_route(self, route, endpoint, *, check_existing=True):
def add_route(self, route, endpoint=None, *, static=True, check_existing=True):
"""Add a route to the API.
:param route: A string representation of the route.
:param endpoint: The endpoint for the route -- can be a callable, a class, a WSGI application, or graphene schema (GraphQL).
:param endpoint: The endpoint for the route -- can be a callable, a class, or graphene schema (GraphQL).
:param static: if True, and no endpoint was passed, render "static/index.html", and forward all undefined routes to this view.
:param check_existing: If ``True``, an AssertionError will be raised, if the route is already defined.
"""
if check_existing:
assert route not in self.routes
if not endpoint and static:
self.static_enabled = True
endpoint = self.static_response
self.routes[route] = Route(route, endpoint)
# TODO: A better datastructer or sort it once the app is loaded
self.routes = dict(
@@ -230,8 +242,17 @@ class API:
)
def default_response(self, req, resp):
resp.status_code = status_codes.HTTP_404
resp.text = "Not found."
if self.static_enabled:
self.static_response(req, resp)
else:
resp.status_code = status_codes.HTTP_404
resp.text = "Not found."
def static_response(self, req, resp):
index = (self.static_dir / "index.html").resolve()
if os.path.exists(index):
with open(index, "r") as f:
resp.text = f.read()
def schema_response(self, req, resp):
resp.status_code = status_codes.HTTP_200
@@ -279,7 +300,7 @@ class API:
return req.text
async def graphql_response(self, req, resp, schema):
show_graphiql = req.method.lower() == "get" and req.accepts("text/html")
show_graphiql = req.method == "get" and req.accepts("text/html")
if show_graphiql:
resp.content = self.template_string(GRAPHIQL, endpoint=req.url.path)
+1
View File
@@ -0,0 +1 @@
lorem
View File
+11
View File
@@ -348,3 +348,14 @@ def test_mount_wsgi_app(api, flask, session):
r = session.get("http://;/flask")
assert r.ok
def test_async_class_based_views(api, session):
@api.route("/")
class Resource:
async def on_post(self, req, resp):
resp.text = await req.text
data = "frame"
r = session.post(api.url_for(Resource), data=data)
assert r.text == data