Add a api.static_app and extend starlette's StaticFiles app

This commit is contained in:
taoufik
2019-08-31 01:33:11 +02:00
parent 85c1c0036c
commit 1bdbea238e
6 changed files with 86 additions and 59 deletions
Generated
+24 -24
View File
@@ -23,10 +23,10 @@
},
"aniso8601": {
"hashes": [
"sha256:b8a6a9b24611fc50cf2d9b45d371bfdc4fd0581d1cc52254f5502130a776d4af",
"sha256:bb167645c79f7a438f9dfab6161af9bed75508c645b1f07d1158240841d22673"
"sha256:513d2b6637b7853806ae79ffaca6f3e8754bdd547048f5ccc1420aec4b714f1e",
"sha256:d10a4bf949f619f719b227ef5386e31f49a2b6d453004b21f02661ccc8670c7b"
],
"version": "==6.0.0"
"version": "==7.0.0"
},
"apispec": {
"hashes": [
@@ -70,10 +70,10 @@
},
"graphene": {
"hashes": [
"sha256:77d61618132ccd084c343e64c22d806cee18dce73cc86e0f427378dbdeeac287",
"sha256:acf808d50d053b94f7958414d511489a9e490a7f9563b9be80f6875fc5723d2a"
"sha256:09165f03e1591b76bf57b133482db9be6dac72c74b0a628d3c93182af9c5a896",
"sha256:2cbe6d4ef15cfc7b7805e0760a0e5b80747161ce1b0f990dfdc0d2cf497c12f9"
],
"version": "==2.1.7"
"version": "==2.1.8"
},
"graphql-core": {
"hashes": [
@@ -158,10 +158,10 @@
},
"marshmallow": {
"hashes": [
"sha256:7ea8540fc7e35be3b0af8b017313944b984d5acdb118b4ba3c270ac9611765c7",
"sha256:bc91e3f90e86133241ac62ea0dd35217d631a207e8628430bc66c347dbe12f7d"
"sha256:23f684b54b1955ebd5bdfbdda4062e438ef86218f14f1a356f570cdf0c016ab3",
"sha256:fcfc9ffd75a883da06f30f604a4e81dd0b56eb9438f4d0a8de6bbaa163ce9ec3"
],
"version": "==3.0.0rc9"
"version": "==3.0.1"
},
"promise": {
"hashes": [
@@ -513,10 +513,10 @@
},
"marshmallow": {
"hashes": [
"sha256:7ea8540fc7e35be3b0af8b017313944b984d5acdb118b4ba3c270ac9611765c7",
"sha256:bc91e3f90e86133241ac62ea0dd35217d631a207e8628430bc66c347dbe12f7d"
"sha256:23f684b54b1955ebd5bdfbdda4062e438ef86218f14f1a356f570cdf0c016ab3",
"sha256:fcfc9ffd75a883da06f30f604a4e81dd0b56eb9438f4d0a8de6bbaa163ce9ec3"
],
"version": "==3.0.0rc9"
"version": "==3.0.1"
},
"mccabe": {
"hashes": [
@@ -590,11 +590,11 @@
},
"pytest": {
"hashes": [
"sha256:3805d095f1ea279b9870c3eeae5dddf8a81b10952c8835cd628cf1875b0ef031",
"sha256:abc562321c2d190dd63c2faadf70b86b7af21a553b61f0df5f5e1270717dc5a3"
"sha256:95d13143cc14174ca1a01ec68e84d76ba5d9d493ac02716fd9706c949a505210",
"sha256:b78fe2881323bd44fd9bd76e5317173d4316577e7b1cddebae9136a4495ec865"
],
"index": "pypi",
"version": "==5.1.0"
"version": "==5.1.2"
},
"pytest-cov": {
"hashes": [
@@ -647,11 +647,11 @@
},
"sphinx": {
"hashes": [
"sha256:22538e1bbe62b407cf5a8aabe1bb15848aa66bb79559f42f5202bbce6b757a69",
"sha256:f9a79e746b87921cabc3baa375199c6076d1270cee53915dbd24fdbeaaacc427"
"sha256:0d586b0f8c2fc3cc6559c5e8fd6124628110514fda0e5d7c82e682d749d2e845",
"sha256:839a3ed6f6b092bb60f492024489cc9e6991360fb9f52ed6361acd510d261069"
],
"index": "pypi",
"version": "==2.1.2"
"version": "==2.2.0"
},
"sphinxcontrib-applehelp": {
"hashes": [
@@ -704,10 +704,10 @@
},
"tqdm": {
"hashes": [
"sha256:1dc82f87a8726602fa7177a091b5e8691d6523138a8f7acd08e58088f51e389f",
"sha256:47220a4f2aeebbc74b0ab317584264ea44c745e1fd5ff316b675cd0aff8afad8"
"sha256:1be3e4e3198f2d0e47b928e9d9a8ec1b63525db29095cec1467f4c5a4ea8ebf9",
"sha256:7e39a30e3d34a7a6539378e39d7490326253b7ee354878a92255656dc4284457"
],
"version": "==4.33.0"
"version": "==4.35.0"
},
"twine": {
"hashes": [
@@ -747,10 +747,10 @@
},
"zipp": {
"hashes": [
"sha256:4970c3758f4e89a7857a973b1e2a5d75bcdc47794442f2e2dd4fe8e0466e809a",
"sha256:8a5712cfd3bb4248015eb3b0b3c54a5f6ee3f2425963ef2a0125b8bc40aafaec"
"sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e",
"sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335"
],
"version": "==0.5.2"
"version": "==0.6.0"
}
}
}
+43 -16
View File
@@ -68,21 +68,6 @@ class API:
self.router = Router()
if openapi or docs_route:
self.openapi = OpenAPISchema(
app=self,
title="Web Service",
version="1.0",
openapi="3.0.2",
docs_route=docs_route,
description=description,
terms_of_service=terms_of_service,
contact=contact,
license=license,
openapi_route=openapi_route,
static_route=static_route,
)
if static_dir is not None:
if static_route is None:
static_route = static_dir
@@ -119,7 +104,7 @@ class API:
os.makedirs(_dir, exist_ok=True)
if self.static_dir is not None:
self.mount(self.static_route, StaticFiles(directory=self.static_dir))
self.mount(self.static_route, self.static_app)
self.formats = get_formats()
@@ -140,12 +125,34 @@ class API:
self.add_middleware(ServerErrorMiddleware, debug=debug)
self.add_middleware(SessionMiddleware, secret_key=self.secret_key)
if openapi or docs_route:
self.openapi = OpenAPISchema(
app=self,
title="Web Service",
version="1.0",
openapi="3.0.2",
docs_route=docs_route,
description=description,
terms_of_service=terms_of_service,
contact=contact,
license=license,
openapi_route=openapi_route,
static_route=static_route,
)
# TODO: Update docs for templates
self.templates = Templates(directory=templates_dir)
self.requests = (
self.session()
) #: A Requests session that is connected to the ASGI app.
@property
def static_app(self):
if not hasattr(self, "_static_app"):
assert self.static_dir is not None
self._static_app = StaticFiles(directory=self.static_dir)
return self._static_app
@staticmethod
def _notfound_wsgi_app(environ, start_response):
start_response("404 NOT FOUND", [("Content-Type", "text/plain")])
@@ -200,6 +207,7 @@ class API:
endpoint=None,
*,
default=False,
static=True,
check_existing=True,
websocket=False,
before_request=False,
@@ -211,6 +219,14 @@ class API:
:param default: If ``True``, all unknown requests will route to this view.
:param static: If ``True``, and no endpoint was passed, render "static/index.html", and it will become a default route.
"""
# Path
if static:
assert self.static_dir is not None
if not endpoint:
endpoint = self._static_response
default = True
self.router.add_route(
route,
endpoint,
@@ -220,6 +236,17 @@ class API:
check_existing=check_existing,
)
async def _static_response(self, req, resp):
assert self.static_dir is not None
index = (self.static_dir / "index.html").resolve()
if os.path.exists(index):
with open(index, "r") as f:
resp.html = "Hello world !"
else:
resp.status_code = status_codes.HTTP_404
resp.text = "Not found."
def redirect(
self, resp, location, *, set_text=True, status_code=status_codes.HTTP_301
):
+1 -1
View File
@@ -57,7 +57,7 @@ class Schema:
self.static_route = static_route
self.app.mount(self.static_route, StaticFiles(directory=theme_path))
self.app.static_app.add_directory(theme_path)
@property
def _apispec(self):
+1 -1
View File
@@ -208,7 +208,7 @@ class WebSocketRoute(BaseRoute):
class Router:
def __init__(self, routes=None, default_response=None, before_requests=None):
self.routes = [] if routes is None else list(routes)
# [TODO] Make it's own router
# [TODO] Make its own router
self.apps = {}
self.default_endpoint = (
self.default_response if default_response is None else default_response
+16 -16
View File
@@ -1,18 +1,18 @@
from whitenoise import WhiteNoise
def _notfound_wsgi_app(environ, start_response):
start_response("404 NOT FOUND", [("Content-Type", "text/plain")])
return [b"Not Found."]
class StaticFiles:
def __init__(self, directory=None, mkdir=True):
self.directory = directory
self.app = WhiteNoise(_notfound_wsgi_app, root=self.directory)
def __call__(self, environ, start_response):
return self.app(environ, start_response)
import typing
from starlette.staticfiles import StaticFiles
class StaticFiles(StaticFiles):
"""I've created an issue to disccuss allowing multiple directories in starletter's `StaticFiles`.
https://github.com/encode/starlette/issues/625
I've also made a PR to add this method to starlette StaticFiles
Once accepted we will remove this.
https://github.com/encode/starlette/pull/626
"""
def add_directory(self, directory: str) -> None:
self.all_directories = [*self.all_directories, *self.get_directories(directory)]
+1 -1
View File
@@ -27,7 +27,7 @@ required = [
"aiofiles",
"pyyaml",
"requests",
"graphene",
"graphene<3.0",
"graphql-server-core>=1.1",
"jinja2",
"uvloop; sys_platform != 'win32' and sys_platform != 'cygwin' and sys_platform != 'cli'",