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.
-
+
{{ request.META }}