Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 40 additions & 42 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,21 @@ keywords = ["web", "framework"]
requires-python = ">=3.10,<4.0"
dependencies = [
"alembic >=1.15.2,<2.0",
"fastapi >=0.115.0",
"click >=8.2",
"granian[reload] >=2.4.0",
"httpx >=0.28.0,<1.0",
"jinja2 >=3.1.2,<4.0",
"packaging >=24.2,<26",
"platformdirs >=4.3.7,<5.0",
"psutil >=7.0.0,<8.0; sys_platform == 'win32'",
"pydantic >=1.10.21,<3.0",
"python-socketio >=5.12.0,<6.0",
"python-multipart >=0.0.20,<1.0",
"python-socketio >=5.12.0,<6.0",
"redis >=5.2.1,<7.0",
"reflex-hosting-cli >=0.1.51",
"rich >=13,<15",
"sqlmodel >=0.0.24,<0.1",
"click >=8.2",
"starlette >=0.47.0",
"typing_extensions >=4.13.0",
"wrapt >=1.17.0,<2.0",
]
Expand All @@ -58,18 +58,49 @@ documentation = "https://reflex.dev/docs/getting-started/introduction"
[project.scripts]
reflex = "reflex.reflex:cli"

[dependency-groups]
dev = [
"asynctest",
"darglint",
"dill",
"fastapi",
"hatchling",
"libsass",
"numpy",
"pandas",
"pillow",
"playwright",
"plotly",
"pre-commit",
"psutil",
"psycopg[binary]",
"pyright",
"pytest-asyncio",
"pytest-benchmark",
"pytest-codspeed",
"pytest-cov",
"pytest-mock",
"pytest-playwright",
"pytest-retry",
"pytest-split",
"pytest",
"python-dotenv",
"ruff",
"selenium",
"starlette-admin",
"toml",
"uvicorn",
]


[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build]
include = ["reflex", "scripts/hatch_build.py"]

[tool.hatch.build.targets.sdist]
artifacts = ["*.pyi"]

[tool.hatch.build.targets.wheel]
artifacts = ["*.pyi"]
targets.sdist.artifacts = ["*.pyi"]
targets.wheel.artifacts = ["*.pyi"]

[tool.hatch.build.hooks.custom]
path = "scripts/hatch_build.py"
Expand Down Expand Up @@ -152,39 +183,6 @@ asyncio_mode = "auto"
skip = "docs/*,*.html,examples/*, *.pyi, poetry.lock, uv.lock"
ignore-words-list = "te, TreeE"

[dependency-groups]
dev = [
"asynctest >=0.13",
"darglint >=1.8",
"dill >=0.3",
"hatchling >=1.27",
"libsass >=0.23",
"numpy >=2.2",
"pandas >=2.2",
"pillow >=11",
"playwright >=1.51",
"plotly >=6.0",
"pre-commit ==4.2.0",
"psutil >=7.0.0",
"psycopg[binary] >=3.2",
"pyright >=1.1.400",
"pytest >=8.3",
"pytest-asyncio >=0.26",
"pytest-benchmark >=5.1",
"pytest-codspeed >=3.2",
"pytest-cov >=6.1",
"pytest-mock >=3.14",
"pytest-playwright >=0.7",
"pytest-retry >=1.7",
"pytest-split >=0.10",
"python-dotenv >=1",
"ruff >=0.11",
"selenium >=4.31",
"starlette-admin >=0.14",
"toml >=0.10.2",
"uvicorn >=0.34.0",
]


[tool.coverage.run]
source = ["reflex"]
Expand Down
26 changes: 6 additions & 20 deletions reflex/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from types import SimpleNamespace
from typing import TYPE_CHECKING, Any, BinaryIO, ParamSpec, get_args, get_type_hints

from fastapi import FastAPI
from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
from socketio import ASGIApp as EngineIOApp
from socketio import AsyncNamespace, AsyncServer
Expand Down Expand Up @@ -441,9 +440,6 @@ class App(MiddlewareMixin, LifespanMixin):
| None
) = None

# FastAPI app for compatibility with FastAPI.
_cached_fastapi_app: FastAPI | None = None

@property
def event_namespace(self) -> EventNamespace | None:
"""Get the event namespace.
Expand Down Expand Up @@ -598,32 +594,22 @@ def __call__(self) -> ASGIApp:
Returns:
The backend api.
"""
from reflex.vars.base import GLOBAL_CACHE

# For py3.9 compatibility when redis is used, we MUST add any decorator pages
# before compiling the app in a thread to avoid event loop error (REF-2172).
self._apply_decorated_pages()

compile_future = concurrent.futures.ThreadPoolExecutor(max_workers=1).submit(
self._compile, prerender_routes=is_prod_mode()
)
self._compile(prerender_routes=is_prod_mode())

def callback(f: concurrent.futures.Future):
# Force background compile errors to print eagerly
return f.result()

compile_future.add_done_callback(callback)
# Wait for the compile to finish to ensure all optional endpoints are mounted.
compile_future.result()
# We will not be making more vars, so we can clear the global cache to free up memory.
GLOBAL_CACHE.clear()

if not self._api:
msg = "The app has not been initialized."
raise ValueError(msg)

if self._cached_fastapi_app is not None:
asgi_app = self._cached_fastapi_app
asgi_app.mount("", self._api)
App._add_cors(asgi_app)
else:
asgi_app = self._api
asgi_app = self._api

if self.api_transformer is not None:
api_transformers: Sequence[Starlette | Callable[[ASGIApp], ASGIApp]] = (
Expand Down
5 changes: 4 additions & 1 deletion reflex/utils/exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,10 @@ def get_reload_paths() -> Sequence[Path]:
module_path = module_path.parent

while module_path.parent.name and _has_child_file(module_path, "__init__.py"):
if _has_child_file(module_path, "rxconfig.py"):
if (
_has_child_file(module_path, "rxconfig.py")
and module_path == Path.cwd()
):
init_file = module_path / "__init__.py"
init_file_content = init_file.read_text()
if init_file_content.strip():
Expand Down
2 changes: 1 addition & 1 deletion tests/units/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

import pytest
import sqlmodel
from fastapi.responses import StreamingResponse
from pytest_mock import MockerFixture
from starlette.applications import Starlette
from starlette.datastructures import UploadFile
from starlette.responses import StreamingResponse
from starlette_admin.auth import AuthProvider
from starlette_admin.contrib.sqla.admin import Admin
from starlette_admin.contrib.sqla.view import ModelView
Expand Down
64 changes: 33 additions & 31 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.