+++ /dev/null
-from io import BytesIO
-import json
-import mimetypes
-import os
-from pathlib import Path
-
-from .utils import scramble
-
-
-class StaticFile:
- template_ext = ".tpl"
- template_filters = {
- b"tojson": lambda value: json.dumps(value)
- }
-
- def __init__(self, path):
- self.path = path
- self.mime_type = mimetypes.guess_type(self.remove_template_ext(str(path)))[0]
- self.mtime = None
- self.content = None
-
- def load_content(self):
- with open(self.path, "rb") as fh:
- return fh.read()
-
- def get(self, context_vars):
- content = self.load_content() if self.path.stat().st_mtime != self.mtime else self.content
- if self.path.suffix == self.template_ext:
- content = self.render(content, context_vars)
- self.content = content
- return content
-
- def render(self, content, context_vars):
- bio = BytesIO()
- pos = 0
- while True:
- new_pos = content.find(b"{{", pos)
- if new_pos < 0:
- break
- bio.write(content[pos:new_pos])
- end_pos = content.find(b"}}", new_pos)
- assert end_pos > 0
- full_tag = content[new_pos + 2:end_pos].split(b"|", 1)
- value = context_vars[full_tag[0].strip().decode()]
- if len(full_tag) == 2:
- value = self.template_filters[full_tag[1].strip()](value)
- bio.write(value.encode())
- pos = end_pos + 2
- bio.write(content[pos:])
- return bio.getvalue()
-
- def __str__(self):
- return f"<StaticFile at \"{os.sep.join(self.path.parts[-2:])}\" [{self.mime_type}]>"
-
- @classmethod
- def remove_template_ext(cls, filename):
- if filename.endswith(cls.template_ext):
- filename = filename[:-4]
- return filename
-
-
-class StaticResource:
- def __init__(self, secret, current_hubapp):
- mimetypes.init()
- self.static_files = {}
- self.context_vars = {}
- self.master_uri = ""
- self.setup(secret, current_hubapp)
-
- def setup(self, secret, current_hubapp):
- hubapp_dir = Path(__file__).parents[1] / "hubapps" / current_hubapp
- for file in os.listdir(hubapp_dir):
- uri_file = StaticFile.remove_template_ext(file)
- if uri_file.startswith("master."):
- uri = f"/{scramble(secret, uri_file)}"
- if uri_file == "master.html":
- self.master_uri = uri
- self.context_vars[uri_file.replace(".", "_")] = uri
- else:
- uri = f"/{uri_file}"
- self.static_files[uri] = StaticFile(hubapp_dir / file)
- if uri_file == "index.html":
- self.static_files["/"] = self.static_files[uri]
-
- async def on_get(self, req, resp):
- path = req.path
- index_uri = f"/index.html"
- if path == "/":
- path = index_uri
- res = self.static_files[path]
- resp.data = res.get(self.context_vars)
- resp.content_type = res.mime_type
-
- def add_routes(self, app):
- for uri_template in self.static_files:
- app.add_route(uri_template, self)