From 24109014afb9d270fc75928f478b770ecd0b5560 Mon Sep 17 00:00:00 2001 From: Joe Kaufeld Date: Mon, 16 Sep 2024 18:15:39 -0400 Subject: [PATCH] :sparkles: add {% static ... %} template option --- example.py | 2 ++ spiderweb/converters.py | 8 ++++++++ spiderweb/jinja_core.py | 16 ++++++++++++++++ spiderweb/jinja_extensions.py | 19 +++++++++++++++++++ spiderweb/main.py | 35 +++++++++++++++++++++++++++++------ templates/test.html | 2 +- 6 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 spiderweb/jinja_core.py create mode 100644 spiderweb/jinja_extensions.py diff --git a/example.py b/example.py index 2ef5881..f071d0b 100644 --- a/example.py +++ b/example.py @@ -26,6 +26,8 @@ app = SpiderwebRouter( staticfiles_dirs=["static_files"], append_slash=False, # default cors_allow_all_origins=True, + static_url="static_stuff", + debug=True, ) diff --git a/spiderweb/converters.py b/spiderweb/converters.py index 939e1c0..a14786d 100644 --- a/spiderweb/converters.py +++ b/spiderweb/converters.py @@ -20,3 +20,11 @@ class FloatConverter: def to_python(self, value): return float(value) + + +class PathConverter: + regex = r".+" + name = "path" + + def to_python(self, value): + return str(value) diff --git a/spiderweb/jinja_core.py b/spiderweb/jinja_core.py new file mode 100644 index 0000000..0de1d7c --- /dev/null +++ b/spiderweb/jinja_core.py @@ -0,0 +1,16 @@ +from typing import TYPE_CHECKING + +from jinja2 import Environment + + +if TYPE_CHECKING: + from spiderweb import SpiderwebRouter + + +class SpiderwebEnvironment(Environment): + # Contains all the normal abilities of the Jinja environment, but with a link + # back to the server for easy access to settings and other server-related + # information. + def __init__(self, server=None, *args, **kwargs): + super().__init__(*args, **kwargs) + self.server: "SpiderwebRouter" = server diff --git a/spiderweb/jinja_extensions.py b/spiderweb/jinja_extensions.py new file mode 100644 index 0000000..33c3158 --- /dev/null +++ b/spiderweb/jinja_extensions.py @@ -0,0 +1,19 @@ +import posixpath + +from jinja2 import nodes +from jinja2.ext import Extension + + +class StaticFilesExtension(Extension): + # Take things that look like `{% static "file" %}` and replace them with `/static/file` + tags = {"static"} + + def parse(self, parser): + token = next(parser.stream) + args = [parser.parse_expression()] + return nodes.Output([self.call_method("_static", args)]).set_lineno( + token.lineno + ) + + def _static(self, file): + return posixpath.join(f"/{self.environment.server.static_url}", file) diff --git a/spiderweb/main.py b/spiderweb/main.py index edf9f79..b99d477 100644 --- a/spiderweb/main.py +++ b/spiderweb/main.py @@ -6,10 +6,10 @@ import traceback import urllib.parse as urlparse from logging import Logger from threading import Thread -from typing import Optional, Callable, Sequence, LiteralString, Literal +from typing import Optional, Callable, Sequence, Literal from wsgiref.simple_server import WSGIServer -from jinja2 import BaseLoader, Environment, FileSystemLoader +from jinja2 import BaseLoader, FileSystemLoader from peewee import Database, SqliteDatabase from spiderweb.middleware import MiddlewareMixin @@ -31,6 +31,7 @@ from spiderweb.exceptions import ( NoResponseError, SpiderwebNetworkException, ) +from spiderweb.jinja_core import SpiderwebEnvironment from spiderweb.local_server import LocalServerMixin from spiderweb.request import Request from spiderweb.response import HttpResponse, TemplateResponse, JsonResponse @@ -61,10 +62,12 @@ class SpiderwebRouter(LocalServerMixin, MiddlewareMixin, RoutesMixin, FernetMixi cors_allow_private_network: bool = False, csrf_trusted_origins: Sequence[str] = None, db: Optional[Database] = None, + debug: bool = False, templates_dirs: Sequence[str] = None, middleware: Sequence[str] = None, append_slash: bool = False, staticfiles_dirs: Sequence[str] = None, + static_url: str = "static", routes: Sequence[tuple[str, Callable] | tuple[str, Callable, dict]] = None, error_routes: dict[int, Callable] = None, secret_key: str = None, @@ -87,6 +90,7 @@ class SpiderwebRouter(LocalServerMixin, MiddlewareMixin, RoutesMixin, FernetMixi self.append_slash = append_slash self.templates_dirs = templates_dirs self.staticfiles_dirs = staticfiles_dirs + self.static_url = static_url self._middleware: list[str] = middleware or [] self.middleware: list[Callable] = [] self.secret_key = secret_key if secret_key else self.generate_key() @@ -109,6 +113,8 @@ class SpiderwebRouter(LocalServerMixin, MiddlewareMixin, RoutesMixin, FernetMixi convert_url_to_regex(i) for i in self._csrf_trusted_origins ] + self.debug = debug + self.extra_data = kwargs # session middleware @@ -144,13 +150,23 @@ class SpiderwebRouter(LocalServerMixin, MiddlewareMixin, RoutesMixin, FernetMixi if self.error_routes: self.add_error_routes() + template_env_args = { + "server": self, + "extensions": [ + "spiderweb.jinja_extensions.StaticFilesExtension", + ], + } + if self.templates_dirs: - self.template_loader = Environment( - loader=FileSystemLoader(self.templates_dirs) + self.template_loader = SpiderwebEnvironment( + loader=FileSystemLoader(self.templates_dirs), + **template_env_args, ) else: self.template_loader = None - self.string_loader = Environment(loader=BaseLoader()) + self.string_loader = SpiderwebEnvironment( + loader=BaseLoader(), **template_env_args + ) if self.staticfiles_dirs: for static_dir in self.staticfiles_dirs: @@ -160,7 +176,14 @@ class SpiderwebRouter(LocalServerMixin, MiddlewareMixin, RoutesMixin, FernetMixi f"Static files directory '{str(static_dir)}' does not exist." ) raise ConfigError - self.add_route(r"/static/", send_file) # noqa: F405 + if self.debug: + # We don't need a log message here because this is the expected behavior + self.add_route(rf"/{self.static_url}/", send_file) # noqa: F405 + else: + self.log.warning( + "`staticfiles_dirs` is set, but `debug` is set to FALSE. Static" + " files will not be served." + ) # finally, run the startup checks to verify everything is correct and happy. self.log.info("Run startup checks...") diff --git a/templates/test.html b/templates/test.html index 6fa59b6..6d2f245 100644 --- a/templates/test.html +++ b/templates/test.html @@ -13,7 +13,7 @@ middleware is working.

- AAAAAAAAAA + AAAAAAAAAA

{{ request.META }}