wip rx._x.asset improvements

This commit is contained in:
Benedikt Bartscher 2024-07-04 20:52:36 +02:00
parent b20f3ac29a
commit 4696f49a03
No known key found for this signature in database
4 changed files with 67 additions and 17 deletions

View File

@ -2,6 +2,7 @@
from .base import ( from .base import (
COOKIES, COOKIES,
ENV_BACKEND_ONLY,
ENV_MODE_ENV_VAR, ENV_MODE_ENV_VAR,
IS_WINDOWS, IS_WINDOWS,
LOCAL_STORAGE, LOCAL_STORAGE,
@ -113,6 +114,7 @@ __ALL__ = [
ROUTER_DATA_INCLUDE, ROUTER_DATA_INCLUDE,
ROUTE_NOT_FOUND, ROUTE_NOT_FOUND,
SETTER_PREFIX, SETTER_PREFIX,
ENV_BACKEND_ONLY,
SKIP_COMPILE_ENV_VAR, SKIP_COMPILE_ENV_VAR,
SocketEvent, SocketEvent,
Tailwind, Tailwind,

View File

@ -188,6 +188,9 @@ SKIP_COMPILE_ENV_VAR = "__REFLEX_SKIP_COMPILE"
# This env var stores the execution mode of the app # This env var stores the execution mode of the app
ENV_MODE_ENV_VAR = "REFLEX_ENV_MODE" ENV_MODE_ENV_VAR = "REFLEX_ENV_MODE"
# This env var can be set to run backend only
ENV_BACKEND_ONLY = "REFLEX_BACKEND_ONLY"
# Testing variables. # Testing variables.
# Testing os env set by pytest when running a test case. # Testing os env set by pytest when running a test case.
PYTEST_CURRENT_TEST = "PYTEST_CURRENT_TEST" PYTEST_CURRENT_TEST = "PYTEST_CURRENT_TEST"

View File

@ -1,16 +1,26 @@
"""Helper functions for adding assets to the app.""" """Helper functions for adding assets to the app."""
import inspect import inspect
import os
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional
from reflex import constants from reflex import constants
def asset(relative_filename: str, subfolder: Optional[str] = None) -> str: def asset(
"""Add an asset to the app. filename: str,
subfolder: Optional[str] = None,
shared: Optional[bool] = None,
) -> str:
"""Add an asset to the app, either shared as a symlink or local.
Shared/External/Library assets:
Place the file next to your including python file. Place the file next to your including python file.
Copies the file to the app's external assets directory. Links the file to the app's external assets directory.
Local/Internal assets:
Place the file in the app's assets/ directory.
Example: Example:
```python ```python
@ -19,14 +29,16 @@ def asset(relative_filename: str, subfolder: Optional[str] = None) -> str:
``` ```
Args: Args:
relative_filename: The relative filename of the asset. filename: The relative filename of the asset.
subfolder: The directory to place the asset in. subfolder: The directory to place the asset in.
shared: Whether to expose the asset to other apps. None means auto-detect.
Raises: Raises:
FileNotFoundError: If the file does not exist. FileNotFoundError: If the file does not exist.
ValueError: If shared is not explicitly set and both shared and local assets exist.
Returns: Returns:
The relative URL to the copied asset. The relative URL to the asset.
""" """
# Determine the file by which the asset is exposed. # Determine the file by which the asset is exposed.
calling_file = inspect.stack()[1].filename calling_file = inspect.stack()[1].filename
@ -36,22 +48,49 @@ def asset(relative_filename: str, subfolder: Optional[str] = None) -> str:
subfolder = f"{caller_module_path}/{subfolder}" if subfolder else caller_module_path subfolder = f"{caller_module_path}/{subfolder}" if subfolder else caller_module_path
src_file = Path(calling_file).parent / relative_filename cwd = Path.cwd()
assets = constants.Dirs.APP_ASSETS assets = constants.Dirs.APP_ASSETS
external = constants.Dirs.EXTERNAL_APP_ASSETS external = constants.Dirs.EXTERNAL_APP_ASSETS
if not src_file.exists(): src_file_shared = Path(calling_file).parent / filename
raise FileNotFoundError(f"File not found: {src_file}") src_file_local = cwd / assets / subfolder / filename
# Create the asset folder in the currently compiling app. shared_exists = src_file_shared.exists()
asset_folder = Path.cwd() / assets / external / subfolder local_exists = src_file_local.exists()
asset_folder.mkdir(parents=True, exist_ok=True)
dst_file = asset_folder / relative_filename # Determine whether the asset is shared or local.
if shared is None:
if shared_exists and local_exists:
raise ValueError(
f"Both shared and local assets exist for {filename}. "
+ "Please explicitly set shared=True or shared=False."
)
if not shared_exists and not local_exists:
raise FileNotFoundError(
f"Could not find file, neither at shared location {src_file_shared} nor at local location {src_file_local}"
)
shared = shared_exists
if not dst_file.exists(): # Local asset handling
dst_file.symlink_to(src_file) if not shared:
if not local_exists:
raise FileNotFoundError(f"File not found: {src_file_local}")
return f"/{filename}"
asset_url = f"/{external}/{subfolder}/{relative_filename}" # Shared asset handling
if not shared_exists:
raise FileNotFoundError(f"File not found: {src_file_shared}")
# Symlink the asset to the app's external assets directory if running frontend.
if not os.environ.get(constants.ENV_BACKEND_ONLY):
# Create the asset folder in the currently compiling app.
asset_folder = Path.cwd() / assets / external / subfolder
asset_folder.mkdir(parents=True, exist_ok=True)
dst_file = asset_folder / filename
if not dst_file.exists():
dst_file.symlink_to(src_file_shared)
asset_url = f"/{external}/{subfolder}/{filename}"
return asset_url return asset_url

View File

@ -242,7 +242,12 @@ def run(
frontend: bool = typer.Option( frontend: bool = typer.Option(
False, "--frontend-only", help="Execute only frontend." False, "--frontend-only", help="Execute only frontend."
), ),
backend: bool = typer.Option(False, "--backend-only", help="Execute only backend."), backend: bool = typer.Option(
False,
"--backend-only",
help="Execute only backend.",
envvar=constants.ENV_BACKEND_ONLY,
),
frontend_port: str = typer.Option( frontend_port: str = typer.Option(
config.frontend_port, help="Specify a different frontend port." config.frontend_port, help="Specify a different frontend port."
), ),
@ -257,6 +262,7 @@ def run(
), ),
): ):
"""Run the app in the current directory.""" """Run the app in the current directory."""
os.environ[constants.ENV_BACKEND_ONLY] = str(backend)
_run(env, frontend, backend, frontend_port, backend_port, backend_host, loglevel) _run(env, frontend, backend, frontend_port, backend_port, backend_host, loglevel)