wip rx._x.asset improvements
This commit is contained in:
parent
b20f3ac29a
commit
4696f49a03
@ -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,
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user