From f9b821aaf197a96056f5df1e95020d2636a70b2a Mon Sep 17 00:00:00 2001 From: Martin Mares <mj@ucw.cz> Date: Sun, 24 Jan 2021 23:29:35 +0100 Subject: [PATCH] =?UTF-8?q?Obecn=C3=BD=20modul=20na=20spr=C3=A1vu=20verzov?= =?UTF-8?q?an=C3=BDch=20statick=C3=BDch=20soubor=C5=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pokusil jsem se napsat ho jako flaskovou extension, aby se dal používat i v jiných projektech. --- mo/ext/__init__.py | 3 +++ mo/ext/assets.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 2 +- 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 mo/ext/__init__.py create mode 100644 mo/ext/assets.py diff --git a/mo/ext/__init__.py b/mo/ext/__init__.py new file mode 100644 index 00000000..76dd78e6 --- /dev/null +++ b/mo/ext/__init__.py @@ -0,0 +1,3 @@ +# mo.ext does nothing by itself + +pass diff --git a/mo/ext/assets.py b/mo/ext/assets.py new file mode 100644 index 00000000..97a9bcdd --- /dev/null +++ b/mo/ext/assets.py @@ -0,0 +1,62 @@ +# Flask extension for versioned assets + +from flask import send_from_directory +import hashlib +import os +from typing import Sequence, Dict + + +class Assets: + + asset_dir: str + asset_dict: Dict[str, str] + url_prefix: str + + def __init__(self, app, url_prefix: str, asset_dir: str): + self.app = app + if app is not None: + self.init_app(app, url_prefix, asset_dir) + + def init_app(self, app, url_prefix: str, asset_dir: str): + self.asset_folder = asset_dir + self.asset_dict = {} + self.url_prefix = url_prefix + self.app = app + app.jinja_env.globals.update(asset_url=lambda name: self.asset_url(name)) + app.assets = self + + # This is usually needed only for development, production requests are handled by upstream proxy + app.add_url_rule( + url_prefix + "/<version>/<path:name>", + endpoint="assets", + view_func=lambda version, name: self.send_asset(name), + ) + + def add_asset(self, name: str): + if name in self.asset_dict: + return + + file_name = os.path.join(self.asset_folder, name) + digest = hashlib.sha1() + + with open(file_name, 'rb') as file: + while True: + block = file.read(4096) + if not block: + break + digest.update(block) + + version = digest.hexdigest()[:8] + self.app.logger.debug(f'Assets: Loaded {name}: version {version}') + self.asset_dict[name] = version + + def add_assets(self, names: Sequence[str]): + for name in names: + self.add_asset(name) + + def asset_url(self, name: str) -> str: + assert name in self.asset_dict + return os.path.join(self.url_prefix, self.asset_dict[name], name) + + def send_asset(self, name: str): + return send_from_directory(self.asset_folder, name) diff --git a/setup.py b/setup.py index 073ae8a1..5b7705e6 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setuptools.setup( name='osmo', version='0.1', description='Odevzdávací systém Matematické olympiády', - packages=['mo', 'mo/jobs', 'mo/web'], + packages=['mo', 'mo/ext', 'mo/jobs', 'mo/web'], scripts=[ 'bin/add-role', 'bin/create-contests', -- GitLab