Source code for shopyo.api.assets

import importlib
import os

from flask import current_app
from flask import send_from_directory
from flask import url_for


[docs] def get_static(boxormodule, filename): """ Generates url for static file. In Shopyo 2.0, this is a thin wrapper around the standard Flask static handler. In Development (DEBUG=True): The request is intercepted by register_shopyo_static. In Production (DEBUG=False): The file is served from the flattened /static/modules/ folder. Args: boxormodule (String): box or module name e.g. box__default/auth or someothermodule filename (String): path of the file inside the box or module Returns ------- URL for static file """ # Standardize on the production-ready path return url_for("static", filename=f"modules/{boxormodule}/{filename}")
[docs] def register_shopyo_static(app, modules_path): """ Registers a transparent interceptor for module static files in debug mode. This allows 'url_for('static', filename='modules/...')' to work dynamically during development without running collectstatic. Args: app (Flask app) modules_path (String): path to the modules directory """ @app.route("/static/modules/<path:boxormodule>/<path:path>") def shopyo_static_interceptor(boxormodule, path): """ Intercepts /static/modules/... and maps it to the physical module folder. """ # 0. Handle Shopyo Plugins and core library (generic: shopyo, shopyo_auth, etc.) # This MUST run before app.debug check because core library assets # (like the logo) are not in the project's local static folder. try: parts = boxormodule.split("/") pkg_name = parts[0] pkg = importlib.import_module(pkg_name) if hasattr(pkg, "view") and hasattr(pkg.view, "mhelp"): pkg_dir = pkg.view.mhelp.dirpath else: pkg_dir = os.path.dirname(pkg.__file__) pkg_static = os.path.join(pkg_dir, "static") # Reconstruct the correct path within pkg_static # if boxormodule is pkg_name/extra/path, we need extra/path + path sub_path = os.path.join(*parts[1:], path) if len(parts) > 1 else path if os.path.exists(os.path.join(pkg_static, sub_path)): return send_from_directory(pkg_static, path=sub_path) except (ImportError, AttributeError): pass if not app.debug: # Standard Flask behavior for non-library modules in production return app.send_static_file(f"modules/{boxormodule}/{path}") # 1. Handle Boxed Modules (e.g., box__default/auth) if "box__" in boxormodule: # Ensure we handle various path formats (box__default/auth or auth inside a box) parts = boxormodule.split("/") if len(parts) >= 2: box = parts[0] module = parts[1] module_static = os.path.join(modules_path, box, module, "static") if os.path.exists(module_static): return send_from_directory(module_static, path=path) # 2. Handle Standard/Flat Modules (local to the project) module_static = os.path.join(modules_path, boxormodule, "static") if os.path.exists(module_static): return send_from_directory(module_static, path=path) # 3. Final Fallback: Try the actual static folder return send_from_directory( os.path.join(app.static_folder, "modules", boxormodule), path=path )
# Backward compatibility for the old name
[docs] def register_devstatic(app, modules_path): return register_shopyo_static(app, modules_path)