[project]
name = "reflex"
dynamic = ["version"]
description = "Web apps in pure Python."
license.text = "Apache-2.0"
authors = [
  { name = "Nikhil Rao" },
  { name = "Alek Petuskey" },
  { name = "Masen Furer" },
  { name = "Elijah Ahianyo" },
  { name = "Thomas Brandeho" },
  { name = "Khaleel Al-Adhami" },
]
maintainers = [
  { name = "Masen Furer" },
  { name = "Khaleel Al-Adhami" },
  { email = "maintainers@reflex.dev" },
]
readme = "README.md"
keywords = ["web", "framework"]
requires-python = ">=3.10,<4.0"
dependencies = [
  "click >=8.2",
  "granian[reload] >=2.7.4",
  "httpx >=0.26,<1.0",
  "packaging >=24.2,<27",
  "psutil >=7.0.0,<8.0; sys_platform == 'win32'",
  "python-multipart >=0.0.32,<1.0",
  "python-socketio >=5.12.0,<6.0",
  "redis >=6.4,<8.0",
  "rich >=13,<16",
  "starlette >=1.3.1",
  "typing_extensions >=4.13.0",
  "wrapt >=1.17.0,<2.2",
  "reflex-base >= 0.9.8",
  "reflex-components-code >= 0.9.0",
  "reflex-components-core >= 0.9.6",
  "reflex-components-dataeditor >= 0.9.0",
  "reflex-components-gridjs >= 0.9.0",
  "reflex-components-lucide >= 0.9.0",
  "reflex-components-markdown >= 0.9.0",
  "reflex-components-moment >= 0.9.0",
  "reflex-components-plotly >= 0.9.0",
  "reflex-components-radix >= 0.9.2",
  "reflex-components-react-player >= 0.9.0",
  "reflex-components-recharts >= 0.9.0",
  "reflex-components-sonner >= 0.9.0",
  "reflex-hosting-cli >= 0.1.66",
]

classifiers = [
  "Development Status :: 4 - Beta",
  "License :: OSI Approved :: Apache Software License",
  "Programming Language :: Python :: 3",
  "Programming Language :: Python :: 3.10",
  "Programming Language :: Python :: 3.11",
  "Programming Language :: Python :: 3.12",
  "Programming Language :: Python :: 3.13",
  "Programming Language :: Python :: 3.14",
]

[project.optional-dependencies]
db = [
  "alembic >=1.15.2,<2.0",
  "pydantic >=2.12.0,<3.0",
  "sqlmodel >=0.0.24,<0.1",
]
pydantic = ["reflex-base[pydantic]"]

[project.urls]
homepage = "https://reflex.dev"
repository = "https://github.com/reflex-dev/reflex"
documentation = "https://reflex.dev/docs/getting-started/introduction"

[project.scripts]
reflex = "reflex.reflex:cli"

[dependency-groups]
dev = [
  "alembic",
  "asynctest",
  "codespell",
  "darglint",
  "dill",
  "fastapi",
  "hatchling",
  "libsass",
  "numpy",
  "pandas",
  "pillow",
  "playwright",
  "plotly",
  "pre-commit",
  "psutil",
  "psycopg[binary]",
  "pydantic",
  "pyright",
  "pytest-asyncio",
  "pytest-benchmark",
  "pytest-codspeed",
  "pytest-cov",
  "pytest-mock",
  "pytest-playwright",
  "pytest-rerunfailures",
  "pytest-split",
  "pytest",
  "python-dotenv",
  "reflex-docgen",
  "reflex-site-shared",
  "ruff",
  "selenium",
  "sqlalchemy",
  "sqlmodel",
  "starlette-admin",
  "toml",
  "towncrier",
  "ty",
  "typer",
  "uvicorn",
]


[build-system]
requires = ["hatchling", "uv-dynamic-versioning"]
build-backend = "hatchling.build"

[tool.hatch.version]
source = "uv-dynamic-versioning"

[tool.uv-dynamic-versioning]
fallback-version = "0.0.0dev0"

[tool.hatch.build]
include = ["reflex", "scripts/hatch_build.py"]
targets.sdist.artifacts = ["*.pyi"]
targets.wheel.artifacts = ["*.pyi"]

[tool.hatch.build.hooks.custom]
path = "scripts/hatch_build.py"
dependencies = ["plotly", "ruff"]
require-runtime-dependencies = true

[tool.pyright]
extraPaths = [
  "packages/reflex-code/src",
  "packages/reflex-components/src",
  "packages/reflex-dataeditor/src",
  "packages/reflex-gridjs/src",
  "packages/reflex-lucide/src",
  "packages/reflex-markdown/src",
  "packages/reflex-moment/src",
  "packages/reflex-plotly/src",
  "packages/reflex-radix/src",
  "packages/reflex-react-player/src",
  "packages/reflex-react-router/src",
  "packages/reflex-recharts/src",
  "packages/reflex-sonner/src",
  "packages/reflex-components-internal/src",
  "packages/reflex-site-shared/src",
  "packages/integrations-docs/src",
]
exclude = [
  ".venv",
  "**/__pycache__",
  "**/.*",
  "**/.templates",
  "**/node_modules",
  "docs",
  "packages/reflex-site-shared",
  "packages/integrations-docs",
  "packages/reflex-ui-shared",
]
reportIncompatibleMethodOverride = false

[tool.ruff]
target-version = "py310"
output-format = "concise"
extend-exclude = ["tests/units/reflex_base/utils/pyi_generator/golden"]
lint.isort.split-on-trailing-comma = false
lint.select = ["ALL"]
lint.ignore = [
  "A",
  "ANN002",
  "ANN003",
  "ANN2",
  "ANN4",
  "ARG",
  "BLE",
  "C901",
  "COM",
  "CPY001",
  "D205",
  "DOC202",
  "DOC501",
  "DOC502",
  "DTZ",
  "E501",
  "F403",
  "FBT",
  "FIX",
  "FURB189",
  "FURB140",
  "G004",
  "ISC003",
  "PLC",
  "PLR",
  "PLW",
  "PT011",
  "PT012",
  "PYI",
  "RUF012",
  "RUF067",
  "S",
  "SLF",
  "SLOT",
  "TC",
  "TD",
  "TRY0",
]
lint.pydocstyle.convention = "google"
lint.flake8-bugbear.extend-immutable-calls = [
  "reflex_base.utils.types.Unset",
  "reflex_base.vars.base.Var.create",
]
preview = true

[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
"tests/*.py" = [
  "ANN001",
  "D100",
  "D103",
  "D104",
  "INP",
  "B018",
  "PERF",
  "T",
  "N",
]
"benchmarks/*.py" = ["ANN001", "D100", "D103", "D104", "B018", "PERF", "T", "N"]
"*/.templates/*.py" = ["D100", "D103", "D104"]
"*.pyi" = ["D301", "D415", "D417", "D418", "E742", "N", "PGH"]
"pyi_generator.py" = ["N802"]
"packages/reflex-base/src/reflex_base/constants/*.py" = ["N"]
"packages/reflex-hosting-cli/src/reflex_cli/**/*.py" = [
  "B008",
  "D420",
  "EM101",
  "EM102",
  "RET504",
]
"tests/units/reflex_cli/**/*.py" = ["DOC201", "PT006", "RUF052"]
"*/.templates/apps/blank/code/*" = ["INP001"]
"*/blank.py" = ["I001"]
"docs/package/scripts/*.py" = ["INP001"]
"scripts/check_min_deps.py" = ["T201"]

[tool.pytest.ini_options]
filterwarnings = "ignore:fields may not start with an underscore:RuntimeWarning"
asyncio_default_fixture_loop_scope = "function"
asyncio_mode = "auto"

[tool.codespell]
skip = "*.html, examples, *.pyi, */nba.csv, */olympic-winners.json, uv.lock, */bun.lock, node_modules"
ignore-words-list = "te, TreeE, selectin"


[tool.coverage.run]
source = [
  "reflex",
  "reflex_components_code",
  "reflex_components_core",
  "reflex_components_dataeditor",
  "reflex_components_gridjs",
  "reflex_components_lucide",
  "reflex_components_markdown",
  "reflex_components_moment",
  "reflex_components_plotly",
  "reflex_components_radix",
  "reflex_components_react_player",
  "reflex_components_recharts",
  "reflex_components_sonner",
  "reflex_base",
  "reflex_docgen",
  "reflex_site_shared",
  "reflex_components_internal",
  "reflex_integrations_docs",
]
branch = true
omit = [
  "*/pyi_generator.py",
  "reflex/__main__.py",
  "reflex/app_module_for_backend.py",
  "reflex/components/chakra/*",
  "reflex/experimental/*",
]

[tool.coverage.report]
show_missing = true
# TODO bump back to 79
fail_under = 72
precision = 2
ignore_errors = true

exclude_also = [
  "def __repr__",
  # Don't complain about missing debug-only code:
  "if self.debug",
  # Don't complain if tests don't hit defensive assertion code:
  "raise AssertionError",
  "raise NotImplementedError",
  # Regexes for lines to exclude from consideration
  "if 0:",
  # Don't complain if non-runnable code isn't run:
  "if __name__ == .__main__.:",
  # Don't complain about abstract methods, they aren't run:
  "@(abc.)?abstractmethod",
  # Don't complain about overloaded methods:
  "@overload",
]

[tool.coverage.html]
directory = "coverage_html_report"

[tool.towncrier]
# Shared monorepo config. package/name intentionally empty — each invocation
# passes --dir <package_path> --name <package> --version <vX.Y.Z> to target a
# specific package. See https://towncrier.readthedocs.io/en/stable/monorepo.html
package = ""
name = ""
directory = "news"
filename = "CHANGELOG.md"
title_format = "## {version} ({project_date})"
issue_format = "[#{issue}](https://github.com/reflex-dev/reflex/issues/{issue})"
start_string = "<!-- towncrier release notes start -->\n"

[[tool.towncrier.type]]
directory = "breaking"
name = "Breaking Changes"
showcontent = true

[[tool.towncrier.type]]
directory = "deprecation"
name = "Deprecations"
showcontent = true

[[tool.towncrier.type]]
directory = "feature"
name = "Features"
showcontent = true

[[tool.towncrier.type]]
directory = "bugfix"
name = "Bug Fixes"
showcontent = true

[[tool.towncrier.type]]
directory = "performance"
name = "Performance"
showcontent = true

[[tool.towncrier.type]]
directory = "docs"
name = "Documentation"
showcontent = true

[[tool.towncrier.type]]
directory = "misc"
name = "Miscellaneous"
showcontent = true

[tool.uv]
required-version = ">=0.9.17"
exclude-newer = "7 days"

# Internal Reflex packages release in lockstep and are routinely pinned (>=) at a version
# published within the exclude-newer window; disable the floor for them so resolution
# always sees their latest release. The floor still applies to third-party dependencies.
# Add any new internal package that is published and pinned as a (build or runtime)
# dependency here.
[tool.uv.exclude-newer-package]
hatch-reflex-pyi = false
reflex = false
reflex-base = false
reflex-components-code = false
reflex-components-core = false
reflex-components-dataeditor = false
reflex-components-gridjs = false
reflex-components-internal = false
reflex-components-lucide = false
reflex-components-markdown = false
reflex-components-moment = false
reflex-components-plotly = false
reflex-components-radix = false
reflex-components-react-player = false
reflex-components-recharts = false
reflex-components-sonner = false
reflex-enterprise = false
reflex-hosting-cli = false
# Pulled in transitively (docs app -> reflex-enterprise -> joserfc), so there is no floor
# to pin here; exempt it so security fixes (CVE-2026-69247 shipped in 50.0.0) resolve as
# soon as they publish instead of waiting out the exclude-newer window.
cryptography = false
# Security fix (CVE-2026-54283 form() DoS) shipped in starlette 1.3.1; exempt so the
# pinned floor resolves before it ages out of the exclude-newer window.
starlette = false

[tool.uv.sources]
hatch-reflex-pyi.workspace = true
reflex-base.workspace = true
reflex-components-code.workspace = true
reflex-components-core.workspace = true
reflex-components-dataeditor.workspace = true
reflex-components-gridjs.workspace = true
reflex-components-lucide.workspace = true
reflex-components-markdown.workspace = true
reflex-components-moment.workspace = true
reflex-components-plotly.workspace = true
reflex-components-radix.workspace = true
reflex-components-react-player.workspace = true
reflex-components-recharts.workspace = true
reflex-components-sonner.workspace = true
reflex-docgen.workspace = true
reflex-hosting-cli.workspace = true
reflex-components-internal.workspace = true
reflex-site-shared.workspace = true
reflex-integrations-docs.workspace = true
reflex.workspace = true

[tool.uv.workspace]
members = ["packages/*", "docs/app", "docs/package"]
