move all environment variables to the same place (#4192)
* move all environment variables to the same place * reorder things around * move more variables to environment * remove cyclical imports * forgot default value for field * for some reason type hints aren't being interpreted * put the field type *before* not after * make it get * move a bit more * add more fields * move reflex dir * add return * put things somewhere else * add custom error
This commit is contained in:
parent
c05da488f9
commit
f39e8c9667
@ -64,7 +64,7 @@ from reflex.components.core.client_side_routing import (
|
|||||||
)
|
)
|
||||||
from reflex.components.core.upload import Upload, get_upload_dir
|
from reflex.components.core.upload import Upload, get_upload_dir
|
||||||
from reflex.components.radix import themes
|
from reflex.components.radix import themes
|
||||||
from reflex.config import get_config
|
from reflex.config import environment, get_config
|
||||||
from reflex.event import Event, EventHandler, EventSpec, window_alert
|
from reflex.event import Event, EventHandler, EventSpec, window_alert
|
||||||
from reflex.model import Model, get_db_status
|
from reflex.model import Model, get_db_status
|
||||||
from reflex.page import (
|
from reflex.page import (
|
||||||
@ -957,15 +957,16 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
|||||||
executor = None
|
executor = None
|
||||||
if (
|
if (
|
||||||
platform.system() in ("Linux", "Darwin")
|
platform.system() in ("Linux", "Darwin")
|
||||||
and os.environ.get("REFLEX_COMPILE_PROCESSES") is not None
|
and (number_of_processes := environment.REFLEX_COMPILE_PROCESSES)
|
||||||
|
is not None
|
||||||
):
|
):
|
||||||
executor = concurrent.futures.ProcessPoolExecutor(
|
executor = concurrent.futures.ProcessPoolExecutor(
|
||||||
max_workers=int(os.environ.get("REFLEX_COMPILE_PROCESSES", 0)) or None,
|
max_workers=number_of_processes,
|
||||||
mp_context=multiprocessing.get_context("fork"),
|
mp_context=multiprocessing.get_context("fork"),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
executor = concurrent.futures.ThreadPoolExecutor(
|
executor = concurrent.futures.ThreadPoolExecutor(
|
||||||
max_workers=int(os.environ.get("REFLEX_COMPILE_THREADS", 0)) or None,
|
max_workers=environment.REFLEX_COMPILE_THREADS
|
||||||
)
|
)
|
||||||
|
|
||||||
with executor:
|
with executor:
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, Iterable, Optional, Type, Union
|
from typing import Dict, Iterable, Optional, Type, Union
|
||||||
@ -16,7 +15,7 @@ from reflex.components.component import (
|
|||||||
CustomComponent,
|
CustomComponent,
|
||||||
StatefulComponent,
|
StatefulComponent,
|
||||||
)
|
)
|
||||||
from reflex.config import get_config
|
from reflex.config import environment, get_config
|
||||||
from reflex.state import BaseState
|
from reflex.state import BaseState
|
||||||
from reflex.style import SYSTEM_COLOR_MODE
|
from reflex.style import SYSTEM_COLOR_MODE
|
||||||
from reflex.utils.exec import is_prod_mode
|
from reflex.utils.exec import is_prod_mode
|
||||||
@ -527,7 +526,7 @@ def remove_tailwind_from_postcss() -> tuple[str, str]:
|
|||||||
|
|
||||||
def purge_web_pages_dir():
|
def purge_web_pages_dir():
|
||||||
"""Empty out .web/pages directory."""
|
"""Empty out .web/pages directory."""
|
||||||
if not is_prod_mode() and os.environ.get("REFLEX_PERSIST_WEB_DIR"):
|
if not is_prod_mode() and environment.REFLEX_PERSIST_WEB_DIR:
|
||||||
# Skip purging the web directory in dev mode if REFLEX_PERSIST_WEB_DIR is set.
|
# Skip purging the web directory in dev mode if REFLEX_PERSIST_WEB_DIR is set.
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Callable, ClassVar, Dict, List, Optional, Tuple
|
from typing import Any, Callable, ClassVar, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
from reflex.components.component import Component, ComponentNamespace, MemoizationLeaf
|
from reflex.components.component import Component, ComponentNamespace, MemoizationLeaf
|
||||||
from reflex.components.el.elements.forms import Input
|
from reflex.components.el.elements.forms import Input
|
||||||
from reflex.components.radix.themes.layout.box import Box
|
from reflex.components.radix.themes.layout.box import Box
|
||||||
|
from reflex.config import environment
|
||||||
from reflex.constants import Dirs
|
from reflex.constants import Dirs
|
||||||
from reflex.event import (
|
from reflex.event import (
|
||||||
CallableEventSpec,
|
CallableEventSpec,
|
||||||
@ -125,9 +125,7 @@ def get_upload_dir() -> Path:
|
|||||||
"""
|
"""
|
||||||
Upload.is_used = True
|
Upload.is_used = True
|
||||||
|
|
||||||
uploaded_files_dir = Path(
|
uploaded_files_dir = environment.REFLEX_UPLOADED_FILES_DIR
|
||||||
os.environ.get("REFLEX_UPLOADED_FILES_DIR", "./uploaded_files")
|
|
||||||
)
|
|
||||||
uploaded_files_dir.mkdir(parents=True, exist_ok=True)
|
uploaded_files_dir.mkdir(parents=True, exist_ok=True)
|
||||||
return uploaded_files_dir
|
return uploaded_files_dir
|
||||||
|
|
||||||
|
198
reflex/config.py
198
reflex/config.py
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import dataclasses
|
||||||
import importlib
|
import importlib
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -9,7 +10,10 @@ import urllib.parse
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional, Set, Union
|
from typing import Any, Dict, List, Optional, Set, Union
|
||||||
|
|
||||||
from reflex.utils.exceptions import ConfigError
|
from typing_extensions import get_type_hints
|
||||||
|
|
||||||
|
from reflex.utils.exceptions import ConfigError, EnvironmentVarValueError
|
||||||
|
from reflex.utils.types import value_inside_optional
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pydantic.v1 as pydantic
|
import pydantic.v1 as pydantic
|
||||||
@ -131,6 +135,198 @@ class DBConfig(Base):
|
|||||||
return f"{self.engine}://{path}/{self.database}"
|
return f"{self.engine}://{path}/{self.database}"
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_value_for_field(field: dataclasses.Field) -> Any:
|
||||||
|
"""Get the default value for a field.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
field: The field.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The default value.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If no default value is found.
|
||||||
|
"""
|
||||||
|
if field.default != dataclasses.MISSING:
|
||||||
|
return field.default
|
||||||
|
elif field.default_factory != dataclasses.MISSING:
|
||||||
|
return field.default_factory()
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"Missing value for environment variable {field.name} and no default value found"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def interpret_boolean_env(value: str) -> bool:
|
||||||
|
"""Interpret a boolean environment variable value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: The environment variable value.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The interpreted value.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
EnvironmentVarValueError: If the value is invalid.
|
||||||
|
"""
|
||||||
|
true_values = ["true", "1", "yes", "y"]
|
||||||
|
false_values = ["false", "0", "no", "n"]
|
||||||
|
|
||||||
|
if value.lower() in true_values:
|
||||||
|
return True
|
||||||
|
elif value.lower() in false_values:
|
||||||
|
return False
|
||||||
|
raise EnvironmentVarValueError(f"Invalid boolean value: {value}")
|
||||||
|
|
||||||
|
|
||||||
|
def interpret_int_env(value: str) -> int:
|
||||||
|
"""Interpret an integer environment variable value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: The environment variable value.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The interpreted value.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
EnvironmentVarValueError: If the value is invalid.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return int(value)
|
||||||
|
except ValueError as ve:
|
||||||
|
raise EnvironmentVarValueError(f"Invalid integer value: {value}") from ve
|
||||||
|
|
||||||
|
|
||||||
|
def interpret_path_env(value: str) -> Path:
|
||||||
|
"""Interpret a path environment variable value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: The environment variable value.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The interpreted value.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
EnvironmentVarValueError: If the path does not exist.
|
||||||
|
"""
|
||||||
|
path = Path(value)
|
||||||
|
if not path.exists():
|
||||||
|
raise EnvironmentVarValueError(f"Path does not exist: {path}")
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def interpret_env_var_value(value: str, field: dataclasses.Field) -> Any:
|
||||||
|
"""Interpret an environment variable value based on the field type.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: The environment variable value.
|
||||||
|
field: The field.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The interpreted value.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the value is invalid.
|
||||||
|
"""
|
||||||
|
field_type = value_inside_optional(field.type)
|
||||||
|
|
||||||
|
if field_type is bool:
|
||||||
|
return interpret_boolean_env(value)
|
||||||
|
elif field_type is str:
|
||||||
|
return value
|
||||||
|
elif field_type is int:
|
||||||
|
return interpret_int_env(value)
|
||||||
|
elif field_type is Path:
|
||||||
|
return interpret_path_env(value)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
f"Invalid type for environment variable {field.name}: {field_type}. This is probably an issue in Reflex."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(init=False)
|
||||||
|
class EnvironmentVariables:
|
||||||
|
"""Environment variables class to instantiate environment variables."""
|
||||||
|
|
||||||
|
# Whether to use npm over bun to install frontend packages.
|
||||||
|
REFLEX_USE_NPM: bool = False
|
||||||
|
|
||||||
|
# The npm registry to use.
|
||||||
|
NPM_CONFIG_REGISTRY: Optional[str] = None
|
||||||
|
|
||||||
|
# Whether to use Granian for the backend. Otherwise, use Uvicorn.
|
||||||
|
REFLEX_USE_GRANIAN: bool = False
|
||||||
|
|
||||||
|
# The username to use for authentication on python package repository. Username and password must both be provided.
|
||||||
|
TWINE_USERNAME: Optional[str] = None
|
||||||
|
|
||||||
|
# The password to use for authentication on python package repository. Username and password must both be provided.
|
||||||
|
TWINE_PASSWORD: Optional[str] = None
|
||||||
|
|
||||||
|
# Whether to use the system installed bun. If set to false, bun will be bundled with the app.
|
||||||
|
REFLEX_USE_SYSTEM_BUN: bool = False
|
||||||
|
|
||||||
|
# Whether to use the system installed node and npm. If set to false, node and npm will be bundled with the app.
|
||||||
|
REFLEX_USE_SYSTEM_NODE: bool = False
|
||||||
|
|
||||||
|
# The working directory for the next.js commands.
|
||||||
|
REFLEX_WEB_WORKDIR: Path = Path(constants.Dirs.WEB)
|
||||||
|
|
||||||
|
# Path to the alembic config file
|
||||||
|
ALEMBIC_CONFIG: Path = Path(constants.ALEMBIC_CONFIG)
|
||||||
|
|
||||||
|
# Disable SSL verification for HTTPX requests.
|
||||||
|
SSL_NO_VERIFY: bool = False
|
||||||
|
|
||||||
|
# The directory to store uploaded files.
|
||||||
|
REFLEX_UPLOADED_FILES_DIR: Path = Path(constants.Dirs.UPLOADED_FILES)
|
||||||
|
|
||||||
|
# Whether to use seperate processes to compile the frontend and how many. If not set, defaults to thread executor.
|
||||||
|
REFLEX_COMPILE_PROCESSES: Optional[int] = None
|
||||||
|
|
||||||
|
# Whether to use seperate threads to compile the frontend and how many. Defaults to `min(32, os.cpu_count() + 4)`.
|
||||||
|
REFLEX_COMPILE_THREADS: Optional[int] = None
|
||||||
|
|
||||||
|
# The directory to store reflex dependencies.
|
||||||
|
REFLEX_DIR: Path = Path(constants.Reflex.DIR)
|
||||||
|
|
||||||
|
# Whether to print the SQL queries if the log level is INFO or lower.
|
||||||
|
SQLALCHEMY_ECHO: bool = False
|
||||||
|
|
||||||
|
# Whether to ignore the redis config error. Some redis servers only allow out-of-band configuration.
|
||||||
|
REFLEX_IGNORE_REDIS_CONFIG_ERROR: bool = False
|
||||||
|
|
||||||
|
# Whether to skip purging the web directory in dev mode.
|
||||||
|
REFLEX_PERSIST_WEB_DIR: bool = False
|
||||||
|
|
||||||
|
# The reflex.build frontend host.
|
||||||
|
REFLEX_BUILD_FRONTEND: str = constants.Templates.REFLEX_BUILD_FRONTEND
|
||||||
|
|
||||||
|
# The reflex.build backend host.
|
||||||
|
REFLEX_BUILD_BACKEND: str = constants.Templates.REFLEX_BUILD_BACKEND
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Initialize the environment variables."""
|
||||||
|
type_hints = get_type_hints(type(self))
|
||||||
|
|
||||||
|
for field in dataclasses.fields(self):
|
||||||
|
raw_value = os.getenv(field.name, None)
|
||||||
|
|
||||||
|
field.type = type_hints.get(field.name) or field.type
|
||||||
|
|
||||||
|
value = (
|
||||||
|
interpret_env_var_value(raw_value, field)
|
||||||
|
if raw_value is not None
|
||||||
|
else get_default_value_for_field(field)
|
||||||
|
)
|
||||||
|
|
||||||
|
setattr(self, field.name, value)
|
||||||
|
|
||||||
|
|
||||||
|
environment = EnvironmentVariables()
|
||||||
|
|
||||||
|
|
||||||
class Config(Base):
|
class Config(Base):
|
||||||
"""The config defines runtime settings for the app.
|
"""The config defines runtime settings for the app.
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
|
||||||
import platform
|
import platform
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from importlib import metadata
|
from importlib import metadata
|
||||||
@ -11,6 +10,8 @@ from types import SimpleNamespace
|
|||||||
|
|
||||||
from platformdirs import PlatformDirs
|
from platformdirs import PlatformDirs
|
||||||
|
|
||||||
|
from .utils import classproperty
|
||||||
|
|
||||||
IS_WINDOWS = platform.system() == "Windows"
|
IS_WINDOWS = platform.system() == "Windows"
|
||||||
|
|
||||||
|
|
||||||
@ -20,6 +21,8 @@ class Dirs(SimpleNamespace):
|
|||||||
# The frontend directories in a project.
|
# The frontend directories in a project.
|
||||||
# The web folder where the NextJS app is compiled to.
|
# The web folder where the NextJS app is compiled to.
|
||||||
WEB = ".web"
|
WEB = ".web"
|
||||||
|
# The directory where uploaded files are stored.
|
||||||
|
UPLOADED_FILES = "uploaded_files"
|
||||||
# The name of the assets directory.
|
# The name of the assets directory.
|
||||||
APP_ASSETS = "assets"
|
APP_ASSETS = "assets"
|
||||||
# The name of the assets directory for external ressource (a subfolder of APP_ASSETS).
|
# The name of the assets directory for external ressource (a subfolder of APP_ASSETS).
|
||||||
@ -64,21 +67,13 @@ class Reflex(SimpleNamespace):
|
|||||||
|
|
||||||
# Files and directories used to init a new project.
|
# Files and directories used to init a new project.
|
||||||
# The directory to store reflex dependencies.
|
# The directory to store reflex dependencies.
|
||||||
# Get directory value from enviroment variables if it exists.
|
# on windows, we use C:/Users/<username>/AppData/Local/reflex.
|
||||||
_dir = os.environ.get("REFLEX_DIR", "")
|
# on macOS, we use ~/Library/Application Support/reflex.
|
||||||
|
# on linux, we use ~/.local/share/reflex.
|
||||||
|
# If user sets REFLEX_DIR envroment variable use that instead.
|
||||||
|
DIR = PlatformDirs(MODULE_NAME, False).user_data_path
|
||||||
|
|
||||||
DIR = Path(
|
|
||||||
_dir
|
|
||||||
or (
|
|
||||||
# on windows, we use C:/Users/<username>/AppData/Local/reflex.
|
|
||||||
# on macOS, we use ~/Library/Application Support/reflex.
|
|
||||||
# on linux, we use ~/.local/share/reflex.
|
|
||||||
# If user sets REFLEX_DIR envroment variable use that instead.
|
|
||||||
PlatformDirs(MODULE_NAME, False).user_data_dir
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# The root directory of the reflex library.
|
# The root directory of the reflex library.
|
||||||
|
|
||||||
ROOT_DIR = Path(__file__).parents[2]
|
ROOT_DIR = Path(__file__).parents[2]
|
||||||
|
|
||||||
RELEASES_URL = f"https://api.github.com/repos/reflex-dev/templates/releases"
|
RELEASES_URL = f"https://api.github.com/repos/reflex-dev/templates/releases"
|
||||||
@ -101,27 +96,51 @@ class Templates(SimpleNamespace):
|
|||||||
DEFAULT = "blank"
|
DEFAULT = "blank"
|
||||||
|
|
||||||
# The reflex.build frontend host
|
# The reflex.build frontend host
|
||||||
REFLEX_BUILD_FRONTEND = os.environ.get(
|
REFLEX_BUILD_FRONTEND = "https://flexgen.reflex.run"
|
||||||
"REFLEX_BUILD_FRONTEND", "https://flexgen.reflex.run"
|
|
||||||
)
|
|
||||||
|
|
||||||
# The reflex.build backend host
|
# The reflex.build backend host
|
||||||
REFLEX_BUILD_BACKEND = os.environ.get(
|
REFLEX_BUILD_BACKEND = "https://flexgen-prod-flexgen.fly.dev"
|
||||||
"REFLEX_BUILD_BACKEND", "https://flexgen-prod-flexgen.fly.dev"
|
|
||||||
)
|
|
||||||
|
|
||||||
# The URL to redirect to reflex.build
|
@classproperty
|
||||||
REFLEX_BUILD_URL = (
|
@classmethod
|
||||||
REFLEX_BUILD_FRONTEND + "/gen?reflex_init_token={reflex_init_token}"
|
def REFLEX_BUILD_URL(cls):
|
||||||
)
|
"""The URL to redirect to reflex.build.
|
||||||
|
|
||||||
# The URL to poll waiting for the user to select a generation.
|
Returns:
|
||||||
REFLEX_BUILD_POLL_URL = REFLEX_BUILD_BACKEND + "/api/init/{reflex_init_token}"
|
The URL to redirect to reflex.build.
|
||||||
|
"""
|
||||||
|
from reflex.config import environment
|
||||||
|
|
||||||
# The URL to fetch the generation's reflex code
|
return (
|
||||||
REFLEX_BUILD_CODE_URL = (
|
environment.REFLEX_BUILD_FRONTEND
|
||||||
REFLEX_BUILD_BACKEND + "/api/gen/{generation_hash}/refactored"
|
+ "/gen?reflex_init_token={reflex_init_token}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classproperty
|
||||||
|
@classmethod
|
||||||
|
def REFLEX_BUILD_POLL_URL(cls):
|
||||||
|
"""The URL to poll waiting for the user to select a generation.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The URL to poll waiting for the user to select a generation.
|
||||||
|
"""
|
||||||
|
from reflex.config import environment
|
||||||
|
|
||||||
|
return environment.REFLEX_BUILD_BACKEND + "/api/init/{reflex_init_token}"
|
||||||
|
|
||||||
|
@classproperty
|
||||||
|
@classmethod
|
||||||
|
def REFLEX_BUILD_CODE_URL(cls):
|
||||||
|
"""The URL to fetch the generation's reflex code.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The URL to fetch the generation's reflex code.
|
||||||
|
"""
|
||||||
|
from reflex.config import environment
|
||||||
|
|
||||||
|
return (
|
||||||
|
environment.REFLEX_BUILD_BACKEND + "/api/gen/{generation_hash}/refactored"
|
||||||
|
)
|
||||||
|
|
||||||
class Dirs(SimpleNamespace):
|
class Dirs(SimpleNamespace):
|
||||||
"""Folders used by the template system of Reflex."""
|
"""Folders used by the template system of Reflex."""
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
"""Config constants."""
|
"""Config constants."""
|
||||||
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
|
|
||||||
@ -9,7 +8,7 @@ from reflex.constants.base import Dirs, Reflex
|
|||||||
from .compiler import Ext
|
from .compiler import Ext
|
||||||
|
|
||||||
# Alembic migrations
|
# Alembic migrations
|
||||||
ALEMBIC_CONFIG = os.environ.get("ALEMBIC_CONFIG", "alembic.ini")
|
ALEMBIC_CONFIG = "alembic.ini"
|
||||||
|
|
||||||
|
|
||||||
class Config(SimpleNamespace):
|
class Config(SimpleNamespace):
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import platform
|
import platform
|
||||||
|
from pathlib import Path
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
|
|
||||||
from .base import IS_WINDOWS, Reflex
|
from .base import IS_WINDOWS
|
||||||
|
from .utils import classproperty
|
||||||
|
|
||||||
|
|
||||||
def get_fnm_name() -> str | None:
|
def get_fnm_name() -> str | None:
|
||||||
@ -36,12 +38,9 @@ class Bun(SimpleNamespace):
|
|||||||
|
|
||||||
# The Bun version.
|
# The Bun version.
|
||||||
VERSION = "1.1.29"
|
VERSION = "1.1.29"
|
||||||
|
|
||||||
# Min Bun Version
|
# Min Bun Version
|
||||||
MIN_VERSION = "0.7.0"
|
MIN_VERSION = "0.7.0"
|
||||||
# The directory to store the bun.
|
|
||||||
ROOT_PATH = Reflex.DIR / "bun"
|
|
||||||
# Default bun path.
|
|
||||||
DEFAULT_PATH = ROOT_PATH / "bin" / ("bun" if not IS_WINDOWS else "bun.exe")
|
|
||||||
|
|
||||||
# URL to bun install script.
|
# URL to bun install script.
|
||||||
INSTALL_URL = "https://raw.githubusercontent.com/reflex-dev/reflex/main/scripts/bun_install.sh"
|
INSTALL_URL = "https://raw.githubusercontent.com/reflex-dev/reflex/main/scripts/bun_install.sh"
|
||||||
@ -50,11 +49,31 @@ class Bun(SimpleNamespace):
|
|||||||
WINDOWS_INSTALL_URL = (
|
WINDOWS_INSTALL_URL = (
|
||||||
"https://raw.githubusercontent.com/reflex-dev/reflex/main/scripts/install.ps1"
|
"https://raw.githubusercontent.com/reflex-dev/reflex/main/scripts/install.ps1"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Path of the bunfig file
|
# Path of the bunfig file
|
||||||
CONFIG_PATH = "bunfig.toml"
|
CONFIG_PATH = "bunfig.toml"
|
||||||
|
|
||||||
# The environment variable to use the system installed bun.
|
@classproperty
|
||||||
USE_SYSTEM_VAR = "REFLEX_USE_SYSTEM_BUN"
|
@classmethod
|
||||||
|
def ROOT_PATH(cls):
|
||||||
|
"""The directory to store the bun.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The directory to store the bun.
|
||||||
|
"""
|
||||||
|
from reflex.config import environment
|
||||||
|
|
||||||
|
return environment.REFLEX_DIR / "bun"
|
||||||
|
|
||||||
|
@classproperty
|
||||||
|
@classmethod
|
||||||
|
def DEFAULT_PATH(cls):
|
||||||
|
"""Default bun path.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The default bun path.
|
||||||
|
"""
|
||||||
|
return cls.ROOT_PATH / "bin" / ("bun" if not IS_WINDOWS else "bun.exe")
|
||||||
|
|
||||||
|
|
||||||
# FNM config.
|
# FNM config.
|
||||||
@ -63,17 +82,36 @@ class Fnm(SimpleNamespace):
|
|||||||
|
|
||||||
# The FNM version.
|
# The FNM version.
|
||||||
VERSION = "1.35.1"
|
VERSION = "1.35.1"
|
||||||
# The directory to store fnm.
|
|
||||||
DIR = Reflex.DIR / "fnm"
|
|
||||||
FILENAME = get_fnm_name()
|
FILENAME = get_fnm_name()
|
||||||
# The fnm executable binary.
|
|
||||||
EXE = DIR / ("fnm.exe" if IS_WINDOWS else "fnm")
|
|
||||||
|
|
||||||
# The URL to the fnm release binary
|
# The URL to the fnm release binary
|
||||||
INSTALL_URL = (
|
INSTALL_URL = (
|
||||||
f"https://github.com/Schniz/fnm/releases/download/v{VERSION}/{FILENAME}.zip"
|
f"https://github.com/Schniz/fnm/releases/download/v{VERSION}/{FILENAME}.zip"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classproperty
|
||||||
|
@classmethod
|
||||||
|
def DIR(cls) -> Path:
|
||||||
|
"""The directory to store fnm.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The directory to store fnm.
|
||||||
|
"""
|
||||||
|
from reflex.config import environment
|
||||||
|
|
||||||
|
return environment.REFLEX_DIR / "fnm"
|
||||||
|
|
||||||
|
@classproperty
|
||||||
|
@classmethod
|
||||||
|
def EXE(cls):
|
||||||
|
"""The fnm executable binary.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The fnm executable binary.
|
||||||
|
"""
|
||||||
|
return cls.DIR / ("fnm.exe" if IS_WINDOWS else "fnm")
|
||||||
|
|
||||||
|
|
||||||
# Node / NPM config
|
# Node / NPM config
|
||||||
class Node(SimpleNamespace):
|
class Node(SimpleNamespace):
|
||||||
@ -84,23 +122,41 @@ class Node(SimpleNamespace):
|
|||||||
# The minimum required node version.
|
# The minimum required node version.
|
||||||
MIN_VERSION = "18.17.0"
|
MIN_VERSION = "18.17.0"
|
||||||
|
|
||||||
# The node bin path.
|
@classproperty
|
||||||
BIN_PATH = (
|
@classmethod
|
||||||
Fnm.DIR
|
def BIN_PATH(cls):
|
||||||
/ "node-versions"
|
"""The node bin path.
|
||||||
/ f"v{VERSION}"
|
|
||||||
/ "installation"
|
|
||||||
/ ("bin" if not IS_WINDOWS else "")
|
|
||||||
)
|
|
||||||
|
|
||||||
# The default path where node is installed.
|
Returns:
|
||||||
PATH = BIN_PATH / ("node.exe" if IS_WINDOWS else "node")
|
The node bin path.
|
||||||
|
"""
|
||||||
|
return (
|
||||||
|
Fnm.DIR
|
||||||
|
/ "node-versions"
|
||||||
|
/ f"v{cls.VERSION}"
|
||||||
|
/ "installation"
|
||||||
|
/ ("bin" if not IS_WINDOWS else "")
|
||||||
|
)
|
||||||
|
|
||||||
# The default path where npm is installed.
|
@classproperty
|
||||||
NPM_PATH = BIN_PATH / "npm"
|
@classmethod
|
||||||
|
def PATH(cls):
|
||||||
|
"""The default path where node is installed.
|
||||||
|
|
||||||
# The environment variable to use the system installed node.
|
Returns:
|
||||||
USE_SYSTEM_VAR = "REFLEX_USE_SYSTEM_NODE"
|
The default path where node is installed.
|
||||||
|
"""
|
||||||
|
return cls.BIN_PATH / ("node.exe" if IS_WINDOWS else "node")
|
||||||
|
|
||||||
|
@classproperty
|
||||||
|
@classmethod
|
||||||
|
def NPM_PATH(cls):
|
||||||
|
"""The default path where npm is installed.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The default path where npm is installed.
|
||||||
|
"""
|
||||||
|
return cls.BIN_PATH / "npm"
|
||||||
|
|
||||||
|
|
||||||
class PackageJson(SimpleNamespace):
|
class PackageJson(SimpleNamespace):
|
||||||
|
32
reflex/constants/utils.py
Normal file
32
reflex/constants/utils.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
"""Utility functions for constants."""
|
||||||
|
|
||||||
|
from typing import Any, Callable, Generic, Type
|
||||||
|
|
||||||
|
from typing_extensions import TypeVar
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
V = TypeVar("V")
|
||||||
|
|
||||||
|
|
||||||
|
class classproperty(Generic[T, V]):
|
||||||
|
"""A class property decorator."""
|
||||||
|
|
||||||
|
def __init__(self, getter: Callable[[Type[T]], V]) -> None:
|
||||||
|
"""Initialize the class property.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
getter: The getter function.
|
||||||
|
"""
|
||||||
|
self.getter = getattr(getter, "__func__", getter)
|
||||||
|
|
||||||
|
def __get__(self, instance: Any, owner: Type[T]) -> V:
|
||||||
|
"""Get the value of the class property.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
instance: The instance of the class.
|
||||||
|
owner: The class itself.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The value of the class property.
|
||||||
|
"""
|
||||||
|
return self.getter(owner)
|
@ -17,7 +17,7 @@ import typer
|
|||||||
from tomlkit.exceptions import TOMLKitError
|
from tomlkit.exceptions import TOMLKitError
|
||||||
|
|
||||||
from reflex import constants
|
from reflex import constants
|
||||||
from reflex.config import get_config
|
from reflex.config import environment, get_config
|
||||||
from reflex.constants import CustomComponents
|
from reflex.constants import CustomComponents
|
||||||
from reflex.utils import console
|
from reflex.utils import console
|
||||||
|
|
||||||
@ -609,14 +609,14 @@ def publish(
|
|||||||
help="The API token to use for authentication on python package repository. If token is provided, no username/password should be provided at the same time",
|
help="The API token to use for authentication on python package repository. If token is provided, no username/password should be provided at the same time",
|
||||||
),
|
),
|
||||||
username: Optional[str] = typer.Option(
|
username: Optional[str] = typer.Option(
|
||||||
os.getenv("TWINE_USERNAME"),
|
environment.TWINE_USERNAME,
|
||||||
"-u",
|
"-u",
|
||||||
"--username",
|
"--username",
|
||||||
show_default="TWINE_USERNAME environment variable value if set",
|
show_default="TWINE_USERNAME environment variable value if set",
|
||||||
help="The username to use for authentication on python package repository. Username and password must both be provided.",
|
help="The username to use for authentication on python package repository. Username and password must both be provided.",
|
||||||
),
|
),
|
||||||
password: Optional[str] = typer.Option(
|
password: Optional[str] = typer.Option(
|
||||||
os.getenv("TWINE_PASSWORD"),
|
environment.TWINE_PASSWORD,
|
||||||
"-p",
|
"-p",
|
||||||
"--password",
|
"--password",
|
||||||
show_default="TWINE_PASSWORD environment variable value if set",
|
show_default="TWINE_PASSWORD environment variable value if set",
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any, ClassVar, Optional, Type, Union
|
from typing import Any, ClassVar, Optional, Type, Union
|
||||||
|
|
||||||
import alembic.autogenerate
|
import alembic.autogenerate
|
||||||
@ -18,9 +16,8 @@ import sqlalchemy
|
|||||||
import sqlalchemy.exc
|
import sqlalchemy.exc
|
||||||
import sqlalchemy.orm
|
import sqlalchemy.orm
|
||||||
|
|
||||||
from reflex import constants
|
|
||||||
from reflex.base import Base
|
from reflex.base import Base
|
||||||
from reflex.config import get_config
|
from reflex.config import environment, get_config
|
||||||
from reflex.utils import console
|
from reflex.utils import console
|
||||||
from reflex.utils.compat import sqlmodel, sqlmodel_field_has_primary_key
|
from reflex.utils.compat import sqlmodel, sqlmodel_field_has_primary_key
|
||||||
|
|
||||||
@ -41,12 +38,12 @@ def get_engine(url: str | None = None) -> sqlalchemy.engine.Engine:
|
|||||||
url = url or conf.db_url
|
url = url or conf.db_url
|
||||||
if url is None:
|
if url is None:
|
||||||
raise ValueError("No database url configured")
|
raise ValueError("No database url configured")
|
||||||
if not Path(constants.ALEMBIC_CONFIG).exists():
|
if environment.ALEMBIC_CONFIG.exists():
|
||||||
console.warn(
|
console.warn(
|
||||||
"Database is not initialized, run [bold]reflex db init[/bold] first."
|
"Database is not initialized, run [bold]reflex db init[/bold] first."
|
||||||
)
|
)
|
||||||
# Print the SQL queries if the log level is INFO or lower.
|
# Print the SQL queries if the log level is INFO or lower.
|
||||||
echo_db_query = os.environ.get("SQLALCHEMY_ECHO") == "True"
|
echo_db_query = environment.SQLALCHEMY_ECHO
|
||||||
# Needed for the admin dash on sqlite.
|
# Needed for the admin dash on sqlite.
|
||||||
connect_args = {"check_same_thread": False} if url.startswith("sqlite") else {}
|
connect_args = {"check_same_thread": False} if url.startswith("sqlite") else {}
|
||||||
return sqlmodel.create_engine(url, echo=echo_db_query, connect_args=connect_args)
|
return sqlmodel.create_engine(url, echo=echo_db_query, connect_args=connect_args)
|
||||||
@ -234,7 +231,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue
|
|||||||
Returns:
|
Returns:
|
||||||
tuple of (config, script_directory)
|
tuple of (config, script_directory)
|
||||||
"""
|
"""
|
||||||
config = alembic.config.Config(constants.ALEMBIC_CONFIG)
|
config = alembic.config.Config(environment.ALEMBIC_CONFIG)
|
||||||
return config, alembic.script.ScriptDirectory(
|
return config, alembic.script.ScriptDirectory(
|
||||||
config.get_main_option("script_location", default="version"),
|
config.get_main_option("script_location", default="version"),
|
||||||
)
|
)
|
||||||
@ -269,8 +266,8 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue
|
|||||||
def alembic_init(cls):
|
def alembic_init(cls):
|
||||||
"""Initialize alembic for the project."""
|
"""Initialize alembic for the project."""
|
||||||
alembic.command.init(
|
alembic.command.init(
|
||||||
config=alembic.config.Config(constants.ALEMBIC_CONFIG),
|
config=alembic.config.Config(environment.ALEMBIC_CONFIG),
|
||||||
directory=str(Path(constants.ALEMBIC_CONFIG).parent / "alembic"),
|
directory=str(environment.ALEMBIC_CONFIG.parent / "alembic"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -290,7 +287,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue
|
|||||||
Returns:
|
Returns:
|
||||||
True when changes have been detected.
|
True when changes have been detected.
|
||||||
"""
|
"""
|
||||||
if not Path(constants.ALEMBIC_CONFIG).exists():
|
if not environment.ALEMBIC_CONFIG.exists():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
config, script_directory = cls._alembic_config()
|
config, script_directory = cls._alembic_config()
|
||||||
@ -391,7 +388,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue
|
|||||||
True - indicating the process was successful.
|
True - indicating the process was successful.
|
||||||
None - indicating the process was skipped.
|
None - indicating the process was skipped.
|
||||||
"""
|
"""
|
||||||
if not Path(constants.ALEMBIC_CONFIG).exists():
|
if not environment.ALEMBIC_CONFIG.exists():
|
||||||
return
|
return
|
||||||
|
|
||||||
with cls.get_db_engine().connect() as connection:
|
with cls.get_db_engine().connect() as connection:
|
||||||
|
@ -13,7 +13,7 @@ from reflex_cli.deployments import deployments_cli
|
|||||||
from reflex_cli.utils import dependency
|
from reflex_cli.utils import dependency
|
||||||
|
|
||||||
from reflex import constants
|
from reflex import constants
|
||||||
from reflex.config import get_config
|
from reflex.config import environment, get_config
|
||||||
from reflex.custom_components.custom_components import custom_components_cli
|
from reflex.custom_components.custom_components import custom_components_cli
|
||||||
from reflex.state import reset_disk_state_manager
|
from reflex.state import reset_disk_state_manager
|
||||||
from reflex.utils import console, redir, telemetry
|
from reflex.utils import console, redir, telemetry
|
||||||
@ -420,7 +420,7 @@ def db_init():
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Check the alembic config.
|
# Check the alembic config.
|
||||||
if Path(constants.ALEMBIC_CONFIG).exists():
|
if environment.ALEMBIC_CONFIG.exists():
|
||||||
console.error(
|
console.error(
|
||||||
"Database is already initialized. Use "
|
"Database is already initialized. Use "
|
||||||
"[bold]reflex db makemigrations[/bold] to create schema change "
|
"[bold]reflex db makemigrations[/bold] to create schema change "
|
||||||
|
@ -8,7 +8,6 @@ import copy
|
|||||||
import dataclasses
|
import dataclasses
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
|
||||||
import pickle
|
import pickle
|
||||||
import sys
|
import sys
|
||||||
import uuid
|
import uuid
|
||||||
@ -64,6 +63,7 @@ from redis.exceptions import ResponseError
|
|||||||
import reflex.istate.dynamic
|
import reflex.istate.dynamic
|
||||||
from reflex import constants
|
from reflex import constants
|
||||||
from reflex.base import Base
|
from reflex.base import Base
|
||||||
|
from reflex.config import environment
|
||||||
from reflex.event import (
|
from reflex.event import (
|
||||||
BACKGROUND_TASK_MARKER,
|
BACKGROUND_TASK_MARKER,
|
||||||
Event,
|
Event,
|
||||||
@ -3274,11 +3274,7 @@ class StateManagerRedis(StateManager):
|
|||||||
)
|
)
|
||||||
except ResponseError:
|
except ResponseError:
|
||||||
# Some redis servers only allow out-of-band configuration, so ignore errors here.
|
# Some redis servers only allow out-of-band configuration, so ignore errors here.
|
||||||
ignore_config_error = os.environ.get(
|
if not environment.REFLEX_IGNORE_REDIS_CONFIG_ERROR:
|
||||||
"REFLEX_IGNORE_REDIS_CONFIG_ERROR",
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
if not ignore_config_error:
|
|
||||||
raise
|
raise
|
||||||
async with self.redis.pubsub() as pubsub:
|
async with self.redis.pubsub() as pubsub:
|
||||||
await pubsub.psubscribe(lock_key_channel)
|
await pubsub.psubscribe(lock_key_channel)
|
||||||
|
@ -23,18 +23,6 @@ def set_env_json():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def set_os_env(**kwargs):
|
|
||||||
"""Set os environment variables.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
kwargs: env key word args.
|
|
||||||
"""
|
|
||||||
for key, value in kwargs.items():
|
|
||||||
if not value:
|
|
||||||
continue
|
|
||||||
os.environ[key.upper()] = value
|
|
||||||
|
|
||||||
|
|
||||||
def generate_sitemap_config(deploy_url: str, export=False):
|
def generate_sitemap_config(deploy_url: str, export=False):
|
||||||
"""Generate the sitemap config file.
|
"""Generate the sitemap config file.
|
||||||
|
|
||||||
|
@ -135,3 +135,7 @@ class SetUndefinedStateVarError(ReflexError, AttributeError):
|
|||||||
|
|
||||||
class StateSchemaMismatchError(ReflexError, TypeError):
|
class StateSchemaMismatchError(ReflexError, TypeError):
|
||||||
"""Raised when the serialized schema of a state class does not match the current schema."""
|
"""Raised when the serialized schema of a state class does not match the current schema."""
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentVarValueError(ReflexError, ValueError):
|
||||||
|
"""Raised when an environment variable is set to an invalid value."""
|
||||||
|
@ -15,7 +15,7 @@ from urllib.parse import urljoin
|
|||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
from reflex import constants
|
from reflex import constants
|
||||||
from reflex.config import get_config
|
from reflex.config import environment, get_config
|
||||||
from reflex.constants.base import LogLevel
|
from reflex.constants.base import LogLevel
|
||||||
from reflex.utils import console, path_ops
|
from reflex.utils import console, path_ops
|
||||||
from reflex.utils.prerequisites import get_web_dir
|
from reflex.utils.prerequisites import get_web_dir
|
||||||
@ -184,7 +184,7 @@ def should_use_granian():
|
|||||||
Returns:
|
Returns:
|
||||||
True if Granian should be used.
|
True if Granian should be used.
|
||||||
"""
|
"""
|
||||||
return os.getenv("REFLEX_USE_GRANIAN", "0") == "1"
|
return environment.REFLEX_USE_GRANIAN
|
||||||
|
|
||||||
|
|
||||||
def get_app_module():
|
def get_app_module():
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
"""Helpers for downloading files from the network."""
|
"""Helpers for downloading files from the network."""
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
|
from ..config import environment
|
||||||
from . import console
|
from . import console
|
||||||
|
|
||||||
|
|
||||||
@ -13,8 +12,7 @@ def _httpx_verify_kwarg() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
True if SSL verification is enabled, False otherwise
|
True if SSL verification is enabled, False otherwise
|
||||||
"""
|
"""
|
||||||
ssl_no_verify = os.environ.get("SSL_NO_VERIFY", "").lower() in ["true", "1", "yes"]
|
return not environment.SSL_NO_VERIFY
|
||||||
return not ssl_no_verify
|
|
||||||
|
|
||||||
|
|
||||||
def get(url: str, **kwargs) -> httpx.Response:
|
def get(url: str, **kwargs) -> httpx.Response:
|
||||||
|
@ -9,6 +9,7 @@ import shutil
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from reflex import constants
|
from reflex import constants
|
||||||
|
from reflex.config import environment
|
||||||
|
|
||||||
# Shorthand for join.
|
# Shorthand for join.
|
||||||
join = os.linesep.join
|
join = os.linesep.join
|
||||||
@ -129,30 +130,13 @@ def which(program: str | Path) -> str | Path | None:
|
|||||||
return shutil.which(str(program))
|
return shutil.which(str(program))
|
||||||
|
|
||||||
|
|
||||||
def use_system_install(var_name: str) -> bool:
|
|
||||||
"""Check if the system install should be used.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
var_name: The name of the environment variable.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: If the variable name is invalid.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Whether the associated env var should use the system install.
|
|
||||||
"""
|
|
||||||
if not var_name.startswith("REFLEX_USE_SYSTEM_"):
|
|
||||||
raise ValueError("Invalid system install variable name.")
|
|
||||||
return os.getenv(var_name, "").lower() in ["true", "1", "yes"]
|
|
||||||
|
|
||||||
|
|
||||||
def use_system_node() -> bool:
|
def use_system_node() -> bool:
|
||||||
"""Check if the system node should be used.
|
"""Check if the system node should be used.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Whether the system node should be used.
|
Whether the system node should be used.
|
||||||
"""
|
"""
|
||||||
return use_system_install(constants.Node.USE_SYSTEM_VAR)
|
return environment.REFLEX_USE_SYSTEM_NODE
|
||||||
|
|
||||||
|
|
||||||
def use_system_bun() -> bool:
|
def use_system_bun() -> bool:
|
||||||
@ -161,7 +145,7 @@ def use_system_bun() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
Whether the system bun should be used.
|
Whether the system bun should be used.
|
||||||
"""
|
"""
|
||||||
return use_system_install(constants.Bun.USE_SYSTEM_VAR)
|
return environment.REFLEX_USE_SYSTEM_BUN
|
||||||
|
|
||||||
|
|
||||||
def get_node_bin_path() -> Path | None:
|
def get_node_bin_path() -> Path | None:
|
||||||
|
@ -33,7 +33,7 @@ from redis.asyncio import Redis
|
|||||||
|
|
||||||
from reflex import constants, model
|
from reflex import constants, model
|
||||||
from reflex.compiler import templates
|
from reflex.compiler import templates
|
||||||
from reflex.config import Config, get_config
|
from reflex.config import Config, environment, get_config
|
||||||
from reflex.utils import console, net, path_ops, processes
|
from reflex.utils import console, net, path_ops, processes
|
||||||
from reflex.utils.exceptions import GeneratedCodeHasNoFunctionDefs
|
from reflex.utils.exceptions import GeneratedCodeHasNoFunctionDefs
|
||||||
from reflex.utils.format import format_library_name
|
from reflex.utils.format import format_library_name
|
||||||
@ -69,8 +69,7 @@ def get_web_dir() -> Path:
|
|||||||
Returns:
|
Returns:
|
||||||
The working directory.
|
The working directory.
|
||||||
"""
|
"""
|
||||||
workdir = Path(os.getenv("REFLEX_WEB_WORKDIR", constants.Dirs.WEB))
|
return environment.REFLEX_WEB_WORKDIR
|
||||||
return workdir
|
|
||||||
|
|
||||||
|
|
||||||
def _python_version_check():
|
def _python_version_check():
|
||||||
@ -250,7 +249,7 @@ def windows_npm_escape_hatch() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
If the user has set REFLEX_USE_NPM.
|
If the user has set REFLEX_USE_NPM.
|
||||||
"""
|
"""
|
||||||
return os.environ.get("REFLEX_USE_NPM", "").lower() in ["true", "1", "yes"]
|
return environment.REFLEX_USE_NPM
|
||||||
|
|
||||||
|
|
||||||
def get_app(reload: bool = False) -> ModuleType:
|
def get_app(reload: bool = False) -> ModuleType:
|
||||||
@ -992,7 +991,7 @@ def needs_reinit(frontend: bool = True) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Make sure the .reflex directory exists.
|
# Make sure the .reflex directory exists.
|
||||||
if not constants.Reflex.DIR.exists():
|
if not environment.REFLEX_DIR.exists():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Make sure the .web directory exists in frontend mode.
|
# Make sure the .web directory exists in frontend mode.
|
||||||
@ -1097,7 +1096,7 @@ def ensure_reflex_installation_id() -> Optional[int]:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
initialize_reflex_user_directory()
|
initialize_reflex_user_directory()
|
||||||
installation_id_file = constants.Reflex.DIR / "installation_id"
|
installation_id_file = environment.REFLEX_DIR / "installation_id"
|
||||||
|
|
||||||
installation_id = None
|
installation_id = None
|
||||||
if installation_id_file.exists():
|
if installation_id_file.exists():
|
||||||
@ -1122,7 +1121,7 @@ def ensure_reflex_installation_id() -> Optional[int]:
|
|||||||
def initialize_reflex_user_directory():
|
def initialize_reflex_user_directory():
|
||||||
"""Initialize the reflex user directory."""
|
"""Initialize the reflex user directory."""
|
||||||
# Create the reflex directory.
|
# Create the reflex directory.
|
||||||
path_ops.mkdir(constants.Reflex.DIR)
|
path_ops.mkdir(environment.REFLEX_DIR)
|
||||||
|
|
||||||
|
|
||||||
def initialize_frontend_dependencies():
|
def initialize_frontend_dependencies():
|
||||||
@ -1145,7 +1144,7 @@ def check_db_initialized() -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
True if alembic is initialized (or if database is not used).
|
True if alembic is initialized (or if database is not used).
|
||||||
"""
|
"""
|
||||||
if get_config().db_url is not None and not Path(constants.ALEMBIC_CONFIG).exists():
|
if get_config().db_url is not None and not environment.ALEMBIC_CONFIG.exists():
|
||||||
console.error(
|
console.error(
|
||||||
"Database is not initialized. Run [bold]reflex db init[/bold] first."
|
"Database is not initialized. Run [bold]reflex db init[/bold] first."
|
||||||
)
|
)
|
||||||
@ -1155,7 +1154,7 @@ def check_db_initialized() -> bool:
|
|||||||
|
|
||||||
def check_schema_up_to_date():
|
def check_schema_up_to_date():
|
||||||
"""Check if the sqlmodel metadata matches the current database schema."""
|
"""Check if the sqlmodel metadata matches the current database schema."""
|
||||||
if get_config().db_url is None or not Path(constants.ALEMBIC_CONFIG).exists():
|
if get_config().db_url is None or not environment.ALEMBIC_CONFIG.exists():
|
||||||
return
|
return
|
||||||
with model.Model.get_db_engine().connect() as connection:
|
with model.Model.get_db_engine().connect() as connection:
|
||||||
try:
|
try:
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
"""Utilities for working with registries."""
|
"""Utilities for working with registries."""
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
|
from reflex.config import environment
|
||||||
from reflex.utils import console, net
|
from reflex.utils import console, net
|
||||||
|
|
||||||
|
|
||||||
@ -56,7 +55,4 @@ def _get_npm_registry() -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
str:
|
str:
|
||||||
"""
|
"""
|
||||||
if npm_registry := os.environ.get("NPM_CONFIG_REGISTRY", ""):
|
return environment.NPM_CONFIG_REGISTRY or get_best_registry()
|
||||||
return npm_registry
|
|
||||||
else:
|
|
||||||
return get_best_registry()
|
|
||||||
|
@ -274,6 +274,20 @@ def is_optional(cls: GenericType) -> bool:
|
|||||||
return is_union(cls) and type(None) in get_args(cls)
|
return is_union(cls) and type(None) in get_args(cls)
|
||||||
|
|
||||||
|
|
||||||
|
def value_inside_optional(cls: GenericType) -> GenericType:
|
||||||
|
"""Get the value inside an Optional type or the original type.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
cls: The class to check.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The value inside the Optional type or the original type.
|
||||||
|
"""
|
||||||
|
if is_union(cls) and len(args := get_args(cls)) >= 2 and type(None) in args:
|
||||||
|
return unionize(*[arg for arg in args if arg is not type(None)])
|
||||||
|
return cls
|
||||||
|
|
||||||
|
|
||||||
def get_property_hint(attr: Any | None) -> GenericType | None:
|
def get_property_hint(attr: Any | None) -> GenericType | None:
|
||||||
"""Check if an attribute is a property and return its type hint.
|
"""Check if an attribute is a property and return its type hint.
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import pytest
|
|||||||
|
|
||||||
import reflex as rx
|
import reflex as rx
|
||||||
import reflex.config
|
import reflex.config
|
||||||
|
from reflex.config import environment
|
||||||
from reflex.constants import Endpoint
|
from reflex.constants import Endpoint
|
||||||
|
|
||||||
|
|
||||||
@ -178,7 +179,7 @@ def test_replace_defaults(
|
|||||||
|
|
||||||
|
|
||||||
def reflex_dir_constant():
|
def reflex_dir_constant():
|
||||||
return rx.constants.Reflex.DIR
|
return environment.REFLEX_DIR
|
||||||
|
|
||||||
|
|
||||||
def test_reflex_dir_env_var(monkeypatch, tmp_path):
|
def test_reflex_dir_env_var(monkeypatch, tmp_path):
|
||||||
|
Loading…
Reference in New Issue
Block a user