move all environment variables to the same place

This commit is contained in:
Khaleel Al-Adhami 2024-10-16 16:34:02 -07:00
parent 101fb1b540
commit 0aeb20f903
4 changed files with 94 additions and 8 deletions

View File

@ -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
@ -10,6 +11,7 @@ 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 reflex.utils.exceptions import ConfigError
from reflex.utils.types import value_inside_optional
try: try:
import pydantic.v1 as pydantic import pydantic.v1 as pydantic
@ -131,6 +133,80 @@ 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"
)
@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
def __init__(self):
"""Initialize the environment variables."""
for field in dataclasses.fields(self):
field_name = field.name
field_type = value_inside_optional(field.type)
if field_type is bool:
true_values = ["true", "1", "yes"]
false_values = ["false", "0", "no"]
value = os.getenv(field_name, None)
if value is not None:
if value.lower() in true_values:
value = True
elif value.lower() in false_values:
value = False
else:
raise ValueError(
f"Invalid value for environment variable {field_name}: {value}"
)
else:
value = get_default_value_for_field(field)
elif field_type is str:
value = os.getenv(field_name, None)
if value is None:
value = get_default_value_for_field(field)
else:
raise ValueError(
f"Invalid type for environment variable {field_name}: {field_type}. This is probably an issue in Reflex."
)
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.

View File

@ -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
@ -250,7 +250,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:

View File

@ -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()

View File

@ -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.