diff options
| -rw-r--r-- | app.py | 111 | ||||
| -rw-r--r-- | pysite/__init__.py | 3 | ||||
| -rw-r--r-- | pysite/base_route.py | 29 | ||||
| -rw-r--r-- | pysite/route_manager.py | 41 | ||||
| -rw-r--r-- | pysite/views/__init__.py | 3 | ||||
| -rw-r--r-- | pysite/views/error_handlers/__init__.py | 3 | ||||
| -rw-r--r-- | pysite/views/error_handlers/http_404.py | 14 | ||||
| -rw-r--r-- | pysite/views/healthcheck.py | 15 | ||||
| -rw-r--r-- | pysite/views/index.py | 12 | ||||
| -rw-r--r-- | pysite/views/invite.py | 15 | ||||
| -rw-r--r-- | requirements-ci.txt | 2 | ||||
| -rw-r--r-- | requirements.txt | 4 | ||||
| -rw-r--r-- | templates/.gitkeep | 0 | 
13 files changed, 110 insertions, 142 deletions
| @@ -1,10 +1,109 @@ -# coding=utf-8 +#!/usr/bin/env python3.6 -from pysite.route_manager import RouteManager +# Stdlib +from importlib.util import module_from_spec, spec_from_file_location +import mimetypes +import os +# External Libraries +from flask import Flask +from werkzeug.wrappers import Response -manager = RouteManager() -app = manager.app +app = Flask() -if __name__ == '__main__': -    manager.run() + +def static_file(path: str):  # type: (str) -> (req: {Response}) -> Coroutine +    async def inner(req):  # type: ({Response}) -> Coroutine +        with open(path) as file: +            return Response( +                response=file.read(), mimetype=mimetypes.guess_type(path)[0]) + +    return inner + + +def find_static_files(dir_: str) -> list:  # type: (str) -> List[str] +    data = [] +    for path, _, files in os.walk(dir_): +        if not files: +            continue + +        for file in files: +            if not file.split(".")[-1] not in ("html", "css", "js"): +                continue + +            pathname = f"{path[len(dir_):]}/{file.strip()}" +            data.append(pathname.split(".")[0], static_file(pathname)) + +    return data + + +def find_routes( +        dir_: str) -> list:  # type: (str) -> List[Tuple[str, str, callable]] +    data = [] +    for path, _, files in os.walk(dir_): +        if not files: +            continue + +        for file in files: +            if not file.endswith(".py"): +                continue +            pathname = f"{path}/{file.strip()}" +            spec = spec_from_file_location(file[:-3], pathname) +            module = module_from_spec(spec) +            spec.loader.exec_module(module) + +            if not hasattr(module, "Index"): +                raise Exception("No `Index` class!") + +            res = module.Index() +            del module, spec + +            route_paths = res.path +            for path_ in route_paths: +                # TODO: Add all request types here +                for method in ("GET", "POST", "DELETE", "PATCH"): +                    if hasattr(res, method.lower()): +                        data.append((path_, method, getattr( +                            res, method.lower()))) + +    return data + + +def find_errors(dir_: str) -> list:  # type: (str) -> List[str] +    data = [] +    for path, _, files in os.walk(dir_): +        if not files: +            continue + +        for file in files: +            if not file.endswith(".py"): +                continue +            pathname = f"{path}/{file.strip()}" +            spec = spec_from_file_location(file[:-3], pathname) +            module = module_from_spec(spec) +            spec.loader.exec_module(module) + +            if not hasattr(module, "Index"): +                raise Exception("No `Index` class!") + +            res = module.Index() +            del module, spec +            data.append((res.error_code, res.err)) + +    return data + + +routes = find_routes("routes") +static = find_static_files("static") +errors = find_errors("error_handlers") + +for path, method, handle in routes: +    app.add_url_rule(path, path, handle, method=method) + +for path, handle in static: +    app.add_url_rule(path, path, handle, method="GET") + +for errcode, handler in errors: +    app.register_error_handler(errcode, handler) + +app.run(port=80) diff --git a/pysite/__init__.py b/pysite/__init__.py deleted file mode 100644 index ba286add..00000000 --- a/pysite/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# coding=utf-8 - -__author__ = "Gareth Coles" diff --git a/pysite/base_route.py b/pysite/base_route.py deleted file mode 100644 index 17e9aee3..00000000 --- a/pysite/base_route.py +++ /dev/null @@ -1,29 +0,0 @@ -# coding=utf-8 -from flask import Flask -from flask.views import MethodView - -__author__ = "Gareth Coles" - - -class BaseView(MethodView): -    path = None  #: str -    name = None  #: str - -    @classmethod -    def setup(cls: "BaseView", app: Flask): -        if not cls.path or not cls.name: -            raise RuntimeError("Route views must have both `path` and `name` defined") - -        app.add_url_rule(cls.path, view_func=cls.as_view(cls.name)) - - -class ErrorView(MethodView): -    name = None  #: str -    error_code = None  #: int - -    @classmethod -    def setup(cls: "ErrorView", app: Flask): -        if not cls.name or not cls.error_code: -            raise RuntimeError("Error views must have both `name` and `error_code` defined") - -        app._register_error_handler(None, cls.error_code, cls.as_view(cls.name)) diff --git a/pysite/route_manager.py b/pysite/route_manager.py deleted file mode 100644 index 501076b7..00000000 --- a/pysite/route_manager.py +++ /dev/null @@ -1,41 +0,0 @@ -# coding=utf-8 -import importlib -import inspect -import os - -from flask import Flask - -from pysite.base_route import BaseView, ErrorView - -__author__ = "Gareth Coles" - - -class RouteManager: -    def __init__(self): -        self.app = Flask(__name__) -        self.app.secret_key = os.environ.get("WEBPAGE_SECRET_KEY") - -        self.load_views() - -    def run(self): -        self.app.run(port=int(os.environ.get("WEBPAGE_PORT")), debug=False) - -    def load_views(self, location="pysite/views"): -        for filename in os.listdir(location): -            if os.path.isdir(f"{location}/{filename}"): -                # Recurse if it's a directory; load ALL the views! -                self.load_views(location=f"{location}/{filename}") -                continue - -            if filename.endswith(".py") and not filename.startswith("__init__"): -                module = importlib.import_module(f"{location}/{filename}".replace("/", ".")[:-3]) - -                for cls_name, cls in inspect.getmembers(module): -                    if ( -                            inspect.isclass(cls) and -                            cls is not BaseView and -                            cls is not ErrorView and -                            (BaseView in cls.__mro__ or ErrorView in cls.__mro__) -                    ): -                        cls.setup(self.app) -                        print(f"View loaded: {cls.name: <25} ({module.__name__}.{cls_name})") diff --git a/pysite/views/__init__.py b/pysite/views/__init__.py deleted file mode 100644 index ba286add..00000000 --- a/pysite/views/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# coding=utf-8 - -__author__ = "Gareth Coles" diff --git a/pysite/views/error_handlers/__init__.py b/pysite/views/error_handlers/__init__.py deleted file mode 100644 index ba286add..00000000 --- a/pysite/views/error_handlers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# coding=utf-8 - -__author__ = "Gareth Coles" diff --git a/pysite/views/error_handlers/http_404.py b/pysite/views/error_handlers/http_404.py deleted file mode 100644 index eea1e630..00000000 --- a/pysite/views/error_handlers/http_404.py +++ /dev/null @@ -1,14 +0,0 @@ -# coding=utf-8 -from werkzeug.exceptions import NotFound - -from pysite.base_route import ErrorView - -__author__ = "Gareth Coles" - - -class Error404View(ErrorView): -    name = "error_404" -    error_code = 404 - -    def get(self, error: NotFound): -        return "replace me with a template, 404 not found", 404 diff --git a/pysite/views/healthcheck.py b/pysite/views/healthcheck.py deleted file mode 100644 index 660c8a96..00000000 --- a/pysite/views/healthcheck.py +++ /dev/null @@ -1,15 +0,0 @@ -# coding=utf-8 -from flask import jsonify - -from pysite.base_route import BaseView - - -__author__ = "Gareth Coles" - - -class IndexView(BaseView): -    path = "/healthcheck" -    name = "healthcheck" - -    def get(self): -        return jsonify({"status": "ok"}) diff --git a/pysite/views/index.py b/pysite/views/index.py deleted file mode 100644 index 2e779003..00000000 --- a/pysite/views/index.py +++ /dev/null @@ -1,12 +0,0 @@ -# coding=utf-8 -from pysite.base_route import BaseView - -__author__ = "Gareth Coles" - - -class IndexView(BaseView): -    path = "/" -    name = "index" - -    def get(self): -        return "Coming soon:tm:" diff --git a/pysite/views/invite.py b/pysite/views/invite.py deleted file mode 100644 index d035fc99..00000000 --- a/pysite/views/invite.py +++ /dev/null @@ -1,15 +0,0 @@ -# coding=utf-8 -from flask import redirect - -from pysite.base_route import BaseView - - -__author__ = "Gareth Coles" - - -class InviteView(BaseView): -    path = "/invite" -    name = "invite" - -    def get(self): -        return redirect("http://invite.pythondiscord.com/") diff --git a/requirements-ci.txt b/requirements-ci.txt index 1ae17a79..0d0490af 100644 --- a/requirements-ci.txt +++ b/requirements-ci.txt @@ -8,3 +8,5 @@ flake8-todo  flake8-string-format   safety   dodgy +isort +yapf diff --git a/requirements.txt b/requirements.txt index 69ca547f..64f1a8bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,3 @@ -flask==0.12.2
\ No newline at end of file +werkzeug +flask +ujson
\ No newline at end of file diff --git a/templates/.gitkeep b/templates/.gitkeep deleted file mode 100644 index e69de29b..00000000 --- a/templates/.gitkeep +++ /dev/null | 
