aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.snekrc19
-rw-r--r--app.py110
-rw-r--r--error_handlers/http_404.py8
-rw-r--r--pysite/__init__.py3
-rw-r--r--pysite/base_route.py29
-rw-r--r--pysite/route_manager.py41
-rw-r--r--pysite/views/__init__.py3
-rw-r--r--pysite/views/error_handlers/__init__.py3
-rw-r--r--pysite/views/error_handlers/http_404.py14
-rw-r--r--pysite/views/healthcheck.py15
-rw-r--r--pysite/views/index.py12
-rw-r--r--pysite/views/invite.py15
-rw-r--r--requirements.txt2
-rw-r--r--routes/healthcheck.py8
-rw-r--r--routes/index.py8
-rw-r--r--routes/invite.py9
-rw-r--r--templates/.gitkeep0
17 files changed, 144 insertions, 155 deletions
diff --git a/.snekrc b/.snekrc
index 1d18fb0c..3f26eea5 100644
--- a/.snekrc
+++ b/.snekrc
@@ -1,21 +1,6 @@
[all]
-linters = flake8, safety, dodgy, yapf, isort
+linters = flake8, safety, dodgy
[flake8]
max-line-length=120
-application_import_names=pysite
-ignore=I100
-
-[isort]
-line_length=120
-indent=' '
-multi_line_output=0
-length_sort=1
-use_parentheses=true
-sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER
-import_heading_stdlib=Stdlib
-import_heading_thirdparty=External Libraries
-import_heading_firstparty=Site Internals
-force_sort_within_sections=true
-
-[style] # yapf \ No newline at end of file
+application_import_names=pysite \ No newline at end of file
diff --git a/app.py b/app.py
index 38770870..f3bb9a60 100644
--- a/app.py
+++ b/app.py
@@ -1,108 +1,10 @@
-#!/usr/bin/env python3.6
+# coding=utf-8
-# Stdlib
-from importlib.util import module_from_spec, spec_from_file_location
-import mimetypes
-import os
+from pysite.route_manager import RouteManager
-# External Libraries
-from japronto import Application
-app = Application()
+manager = RouteManager()
+app = manager.app
-
-def static_file(path: str): # type: (str) -> (req: {Response}) -> Coroutine
- async def inner(req): # type: ({Response}) -> Coroutine
- with open(path) as file:
- return req.Response(
- text=file.read(), mime_type=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.router.add_route(path, handle, method=method)
-
-for path, handle in static:
- app.router.add_route(path, handle, method="GET")
-
-for errcode, handler in errors:
- app.add_error_handler(errcode, handler)
-
-app.run(debug=True, port=80)
+if __name__ == '__main__':
+ manager.run()
diff --git a/error_handlers/http_404.py b/error_handlers/http_404.py
deleted file mode 100644
index 712bf748..00000000
--- a/error_handlers/http_404.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# coding=utf-8
-
-
-class Index:
- error_code = 404
-
- def err(self, req):
- return req.Response(text="Page not found!", code=404)
diff --git a/pysite/__init__.py b/pysite/__init__.py
new file mode 100644
index 00000000..ba286add
--- /dev/null
+++ b/pysite/__init__.py
@@ -0,0 +1,3 @@
+# coding=utf-8
+
+__author__ = "Gareth Coles"
diff --git a/pysite/base_route.py b/pysite/base_route.py
new file mode 100644
index 00000000..76338280
--- /dev/null
+++ b/pysite/base_route.py
@@ -0,0 +1,29 @@
+# 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, 404, cls.as_view(cls.name))
diff --git a/pysite/route_manager.py b/pysite/route_manager.py
new file mode 100644
index 00000000..501076b7
--- /dev/null
+++ b/pysite/route_manager.py
@@ -0,0 +1,41 @@
+# 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
new file mode 100644
index 00000000..ba286add
--- /dev/null
+++ b/pysite/views/__init__.py
@@ -0,0 +1,3 @@
+# coding=utf-8
+
+__author__ = "Gareth Coles"
diff --git a/pysite/views/error_handlers/__init__.py b/pysite/views/error_handlers/__init__.py
new file mode 100644
index 00000000..ba286add
--- /dev/null
+++ b/pysite/views/error_handlers/__init__.py
@@ -0,0 +1,3 @@
+# coding=utf-8
+
+__author__ = "Gareth Coles"
diff --git a/pysite/views/error_handlers/http_404.py b/pysite/views/error_handlers/http_404.py
new file mode 100644
index 00000000..eea1e630
--- /dev/null
+++ b/pysite/views/error_handlers/http_404.py
@@ -0,0 +1,14 @@
+# 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
new file mode 100644
index 00000000..660c8a96
--- /dev/null
+++ b/pysite/views/healthcheck.py
@@ -0,0 +1,15 @@
+# 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
new file mode 100644
index 00000000..2e779003
--- /dev/null
+++ b/pysite/views/index.py
@@ -0,0 +1,12 @@
+# 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
new file mode 100644
index 00000000..d035fc99
--- /dev/null
+++ b/pysite/views/invite.py
@@ -0,0 +1,15 @@
+# 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.txt b/requirements.txt
index 8f1f53e4..69ca547f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1 @@
-japronto
+flask==0.12.2 \ No newline at end of file
diff --git a/routes/healthcheck.py b/routes/healthcheck.py
deleted file mode 100644
index 11a5fc24..00000000
--- a/routes/healthcheck.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# coding=utf-8
-
-
-class Index:
- path = ["/healthcheck"]
-
- def get(self, req):
- return req.Response(json={"status": "ok"})
diff --git a/routes/index.py b/routes/index.py
deleted file mode 100644
index 76671ed1..00000000
--- a/routes/index.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# coding=utf-8
-
-
-class Index:
- path = ["/", "/index"]
-
- def get(self, req):
- return req.Response("Coming soon:tm:")
diff --git a/routes/invite.py b/routes/invite.py
deleted file mode 100644
index 29553345..00000000
--- a/routes/invite.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# coding=utf-8
-
-
-class Index:
- path = ["/invite"]
-
- def get(self, res):
- return res.Response(
- status_code=301, text="http://invite.pythondiscord.com/")
diff --git a/templates/.gitkeep b/templates/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/templates/.gitkeep