From 61a6ab9bbd89e84a243c8fc68145ddf8813f5903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Mon, 27 Jan 2025 12:37:00 -0800 Subject: [PATCH 01/13] fix stuff with bun_path (#4688) * fix stuff with bun_path * which always return Path object * try using samefile() for file path comparison * check for None * fix tests, maybe * fix more tests --- reflex/utils/exec.py | 10 +++++----- reflex/utils/path_ops.py | 35 ++++++++++++++++++++++----------- reflex/utils/prerequisites.py | 23 ++++++++++------------ tests/units/utils/test_utils.py | 11 +++++------ 4 files changed, 43 insertions(+), 36 deletions(-) diff --git a/reflex/utils/exec.py b/reflex/utils/exec.py index 88603da64..1e5cda10b 100644 --- a/reflex/utils/exec.py +++ b/reflex/utils/exec.py @@ -467,19 +467,19 @@ def output_system_info(): system = platform.system() + fnm_info = f"[FNM {prerequisites.get_fnm_version()} (Expected: {constants.Fnm.VERSION}) (PATH: {constants.Fnm.EXE})]" + if system != "Windows" or ( system == "Windows" and prerequisites.is_windows_bun_supported() ): dependencies.extend( [ - f"[FNM {prerequisites.get_fnm_version()} (Expected: {constants.Fnm.VERSION}) (PATH: {constants.Fnm.EXE})]", - f"[Bun {prerequisites.get_bun_version()} (Expected: {constants.Bun.VERSION}) (PATH: {config.bun_path})]", + fnm_info, + f"[Bun {prerequisites.get_bun_version()} (Expected: {constants.Bun.VERSION}) (PATH: {path_ops.get_bun_path()})]", ], ) else: - dependencies.append( - f"[FNM {prerequisites.get_fnm_version()} (Expected: {constants.Fnm.VERSION}) (PATH: {constants.Fnm.EXE})]", - ) + dependencies.append(fnm_info) if system == "Linux": import distro # type: ignore diff --git a/reflex/utils/path_ops.py b/reflex/utils/path_ops.py index e3256bb45..edab085ff 100644 --- a/reflex/utils/path_ops.py +++ b/reflex/utils/path_ops.py @@ -9,7 +9,7 @@ import shutil from pathlib import Path from reflex import constants -from reflex.config import environment +from reflex.config import environment, get_config # Shorthand for join. join = os.linesep.join @@ -118,7 +118,7 @@ def ln(src: str | Path, dest: str | Path, overwrite: bool = False) -> bool: return True -def which(program: str | Path) -> str | Path | None: +def which(program: str | Path) -> Path | None: """Find the path to an executable. Args: @@ -127,7 +127,8 @@ def which(program: str | Path) -> str | Path | None: Returns: The path to the executable. """ - return shutil.which(str(program)) + which_result = shutil.which(program) + return Path(which_result) if which_result else None def use_system_node() -> bool: @@ -156,12 +157,12 @@ def get_node_bin_path() -> Path | None: """ bin_path = Path(constants.Node.BIN_PATH) if not bin_path.exists(): - str_path = which("node") - return Path(str_path).parent.resolve() if str_path else None - return bin_path.resolve() + path = which("node") + return path.parent.absolute() if path else None + return bin_path.absolute() -def get_node_path() -> str | None: +def get_node_path() -> Path | None: """Get the node binary path. Returns: @@ -169,9 +170,8 @@ def get_node_path() -> str | None: """ node_path = Path(constants.Node.PATH) if use_system_node() or not node_path.exists(): - system_node_path = which("node") - return str(system_node_path) if system_node_path else None - return str(node_path) + node_path = which("node") + return node_path def get_npm_path() -> Path | None: @@ -182,11 +182,22 @@ def get_npm_path() -> Path | None: """ npm_path = Path(constants.Node.NPM_PATH) if use_system_node() or not npm_path.exists(): - system_npm_path = which("npm") - npm_path = Path(system_npm_path) if system_npm_path else None + npm_path = which("npm") return npm_path.absolute() if npm_path else None +def get_bun_path() -> Path | None: + """Get bun binary path. + + Returns: + The path to the bun binary file. + """ + bun_path = get_config().bun_path + if use_system_bun() or not bun_path.exists(): + bun_path = which("bun") + return bun_path.absolute() if bun_path else None + + def update_json_file(file_path: str | Path, update_dict: dict[str, int | str]): """Update the contents of a json file. diff --git a/reflex/utils/prerequisites.py b/reflex/utils/prerequisites.py index 2a890f821..66c9156a9 100644 --- a/reflex/utils/prerequisites.py +++ b/reflex/utils/prerequisites.py @@ -205,10 +205,13 @@ def get_bun_version() -> version.Version | None: Returns: The version of bun. """ + bun_path = path_ops.get_bun_path() + if bun_path is None: + return None try: # Run the bun -v command and capture the output - result = processes.new_process([str(get_config().bun_path), "-v"], run=True) - return version.parse(result.stdout) # type: ignore + result = processes.new_process([str(bun_path), "-v"], run=True) + return version.parse(str(result.stdout)) except FileNotFoundError: return None except version.InvalidVersion as e: @@ -1062,9 +1065,7 @@ def install_bun(): ) # Skip if bun is already installed. - if Path(get_config().bun_path).exists() and get_bun_version() == version.parse( - constants.Bun.VERSION - ): + if get_bun_version() == version.parse(constants.Bun.VERSION): console.debug("Skipping bun installation as it is already installed.") return @@ -1085,8 +1086,7 @@ def install_bun(): show_logs=console.is_debug(), ) else: - unzip_path = path_ops.which("unzip") - if unzip_path is None: + if path_ops.which("unzip") is None: raise SystemPackageMissingError("unzip") # Run the bun install script. @@ -1290,12 +1290,9 @@ def validate_bun(): Raises: Exit: If custom specified bun does not exist or does not meet requirements. """ - # if a custom bun path is provided, make sure its valid - # This is specific to non-FHS OS - bun_path = get_config().bun_path - if path_ops.use_system_bun(): - bun_path = path_ops.which("bun") - if bun_path != constants.Bun.DEFAULT_PATH: + bun_path = path_ops.get_bun_path() + + if bun_path and bun_path.samefile(constants.Bun.DEFAULT_PATH): console.info(f"Using custom Bun path: {bun_path}") bun_version = get_bun_version() if not bun_version: diff --git a/tests/units/utils/test_utils.py b/tests/units/utils/test_utils.py index f8573111c..65e77f4a7 100644 --- a/tests/units/utils/test_utils.py +++ b/tests/units/utils/test_utils.py @@ -122,13 +122,13 @@ def test_validate_invalid_bun_path(mocker): Args: mocker: Pytest mocker object. """ - mock = mocker.Mock() - mocker.patch.object(mock, "bun_path", return_value="/mock/path") - mocker.patch("reflex.utils.prerequisites.get_config", mock) + mock_path = mocker.Mock() + mocker.patch("reflex.utils.path_ops.get_bun_path", return_value=mock_path) mocker.patch("reflex.utils.prerequisites.get_bun_version", return_value=None) with pytest.raises(typer.Exit): prerequisites.validate_bun() + mock_path.samefile.assert_called_once() def test_validate_bun_path_incompatible_version(mocker): @@ -137,9 +137,8 @@ def test_validate_bun_path_incompatible_version(mocker): Args: mocker: Pytest mocker object. """ - mock = mocker.Mock() - mocker.patch.object(mock, "bun_path", return_value="/mock/path") - mocker.patch("reflex.utils.prerequisites.get_config", mock) + mock_path = mocker.Mock() + mocker.patch("reflex.utils.path_ops.get_bun_path", return_value=mock_path) mocker.patch( "reflex.utils.prerequisites.get_bun_version", return_value=version.parse("0.6.5"), From 4d08484a121b936a30ca9c396b2de4375f03ba33 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Mon, 27 Jan 2025 21:31:14 -0800 Subject: [PATCH 02/13] import vars are not sortable (#4700) --- reflex/utils/imports.py | 2 +- reflex/vars/base.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/reflex/utils/imports.py b/reflex/utils/imports.py index bd422ecc0..ab217087c 100644 --- a/reflex/utils/imports.py +++ b/reflex/utils/imports.py @@ -90,7 +90,7 @@ def collapse_imports( } -@dataclasses.dataclass(order=True, frozen=True) +@dataclasses.dataclass(frozen=True) class ImportVar: """An import var.""" diff --git a/reflex/vars/base.py b/reflex/vars/base.py index 8fb543c99..f6359166f 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -145,9 +145,7 @@ class VarData: position: Position of the hook in the component. """ immutable_imports: ImmutableParsedImportDict = tuple( - sorted( - ((k, tuple(sorted(v))) for k, v in parse_imports(imports or {}).items()) - ) + (k, tuple(v)) for k, v in parse_imports(imports or {}).items() ) object.__setattr__(self, "state", state) object.__setattr__(self, "field_name", field_name) From 9e36efbd21eb92ae216eee49417aa5533932967e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Tue, 28 Jan 2025 14:20:26 +0100 Subject: [PATCH 03/13] fix version in pyproject and ruff version check (#4690) * fix version in pyproject and ruff version check * relock deps * relax some strict values --- poetry.lock | 264 ++++++++++++++++++++++- pyproject.toml | 4 +- reflex/app.py | 8 +- reflex/components/core/breakpoints.py | 4 +- reflex/event.py | 4 +- reflex/state.py | 1 + reflex/utils/types.py | 10 +- reflex/vars/base.py | 2 +- tests/units/compiler/test_compiler.py | 2 +- tests/units/components/test_component.py | 2 + tests/units/test_var.py | 3 + 11 files changed, 288 insertions(+), 16 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5cc673489..68e8e37db 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand. [[package]] name = "alembic" @@ -6,6 +6,8 @@ version = "1.14.1" description = "A database migration tool for SQLAlchemy." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "alembic-1.14.1-py3-none-any.whl", hash = "sha256:1acdd7a3a478e208b0503cd73614d5e4c6efafa4e73518bb60e4f2846a37b1c5"}, {file = "alembic-1.14.1.tar.gz", hash = "sha256:496e888245a53adf1498fcab31713a469c65836f8de76e01399aa1c3e90dd213"}, @@ -25,6 +27,8 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -36,6 +40,8 @@ version = "4.8.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, @@ -58,6 +64,8 @@ version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_full_version < \"3.11.3\"" files = [ {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, @@ -69,6 +77,8 @@ version = "0.13.0" description = "Enhance the standard unittest package with features for testing asyncio libraries" optional = false python-versions = ">=3.5" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "asynctest-0.13.0-py3-none-any.whl", hash = "sha256:5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676"}, {file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"}, @@ -80,6 +90,8 @@ version = "24.3.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"}, {file = "attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff"}, @@ -99,6 +111,8 @@ version = "1.2.0" description = "Backport of CPython tarfile module" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "(platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and python_version <= \"3.11\"" files = [ {file = "backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34"}, {file = "backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991"}, @@ -114,6 +128,8 @@ version = "0.23.1" description = "The bidirectional mapping library for Python." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5"}, {file = "bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71"}, @@ -125,6 +141,8 @@ version = "1.2.2.post1" description = "A simple, correct Python build frontend" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5"}, {file = "build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7"}, @@ -150,6 +168,8 @@ version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, @@ -161,6 +181,7 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -230,6 +251,7 @@ files = [ {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] +markers = {main = "(platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" and platform_python_implementation != \"PyPy\" and (python_version <= \"3.11\" or python_version >= \"3.12\")", dev = "os_name == \"nt\" and implementation_name != \"pypy\" and (python_version <= \"3.11\" or python_version >= \"3.12\")"} [package.dependencies] pycparser = "*" @@ -240,6 +262,8 @@ version = "3.4.0" description = "Validate configuration and produce human readable error messages." optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, @@ -251,6 +275,8 @@ version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, @@ -352,6 +378,8 @@ version = "8.1.8" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, @@ -366,10 +394,12 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "(platform_system == \"Windows\" or os_name == \"nt\") and (python_version <= \"3.11\" or python_version >= \"3.12\")", dev = "(python_version <= \"3.11\" or python_version >= \"3.12\") and sys_platform == \"win32\""} [[package]] name = "coverage" @@ -377,6 +407,8 @@ version = "7.6.10" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78"}, {file = "coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c"}, @@ -454,6 +486,8 @@ version = "44.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.7" +groups = ["main"] +markers = "(platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" and (python_version <= \"3.11\" or python_version >= \"3.12\")" files = [ {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, @@ -461,6 +495,7 @@ files = [ {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, @@ -471,6 +506,7 @@ files = [ {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, @@ -503,6 +539,8 @@ version = "1.8.1" description = "A utility for ensuring Google-style docstrings stay up to date with the source code." optional = false python-versions = ">=3.6,<4.0" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, @@ -514,6 +552,8 @@ version = "0.3.9" description = "serialize all of Python" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a"}, {file = "dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c"}, @@ -529,6 +569,8 @@ version = "0.3.9" description = "Distribution utilities" optional = false python-versions = "*" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, @@ -540,6 +582,8 @@ version = "1.9.0" description = "Distro - an OS platform information API" optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "(python_version <= \"3.11\" or python_version >= \"3.12\") and sys_platform == \"linux\"" files = [ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, @@ -551,6 +595,8 @@ version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, @@ -562,6 +608,8 @@ version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -576,6 +624,8 @@ version = "0.115.6" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "fastapi-0.115.6-py3-none-any.whl", hash = "sha256:e9240b29e36fa8f4bb7290316988e90c381e5092e0cbe84e7818cc3713bcf305"}, {file = "fastapi-0.115.6.tar.gz", hash = "sha256:9ec46f7addc14ea472958a96aae5b5de65f39721a46aaf5705c480d9a8b76654"}, @@ -596,6 +646,8 @@ version = "3.17.0" description = "A platform independent file lock." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338"}, {file = "filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e"}, @@ -612,6 +664,7 @@ version = "3.1.1" description = "Lightweight in-process concurrent programming" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563"}, {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83"}, @@ -687,6 +740,7 @@ files = [ {file = "greenlet-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22"}, {file = "greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467"}, ] +markers = {main = "python_version < \"3.14\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\") and (python_version <= \"3.11\" or python_version >= \"3.12\")", dev = "python_version <= \"3.11\" or python_version >= \"3.12\""} [package.extras] docs = ["Sphinx", "furo"] @@ -698,6 +752,8 @@ version = "23.0.0" description = "WSGI HTTP Server for UNIX" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "gunicorn-23.0.0-py3-none-any.whl", hash = "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d"}, {file = "gunicorn-23.0.0.tar.gz", hash = "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec"}, @@ -719,6 +775,8 @@ version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, @@ -730,6 +788,8 @@ version = "1.0.7" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, @@ -751,6 +811,8 @@ version = "0.28.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, @@ -775,6 +837,8 @@ version = "1.5.0" description = "A tool for generating OIDC identities" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "id-1.5.0-py3-none-any.whl", hash = "sha256:f1434e1cef91f2cbb8a4ec64663d5a23b9ed43ef44c4c957d02583d61714c658"}, {file = "id-1.5.0.tar.gz", hash = "sha256:292cb8a49eacbbdbce97244f47a97b4c62540169c976552e497fd57df0734c1d"}, @@ -794,6 +858,8 @@ version = "2.6.6" description = "File identification library for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "identify-2.6.6-py2.py3-none-any.whl", hash = "sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881"}, {file = "identify-2.6.6.tar.gz", hash = "sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251"}, @@ -808,6 +874,8 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -822,6 +890,8 @@ version = "8.6.1" description = "Read metadata from Python packages" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "(platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and python_version <= \"3.11\" or python_full_version < \"3.10.2\"" files = [ {file = "importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e"}, {file = "importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580"}, @@ -845,6 +915,8 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -856,6 +928,8 @@ version = "3.4.0" description = "Utility functions for Python class constructs" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "(python_version <= \"3.11\" or python_version >= \"3.12\") and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\")" files = [ {file = "jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790"}, {file = "jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd"}, @@ -874,6 +948,8 @@ version = "6.0.1" description = "Useful decorators and context managers" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "(python_version <= \"3.11\" or python_version >= \"3.12\") and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\")" files = [ {file = "jaraco.context-6.0.1-py3-none-any.whl", hash = "sha256:f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4"}, {file = "jaraco_context-6.0.1.tar.gz", hash = "sha256:9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3"}, @@ -892,6 +968,8 @@ version = "4.1.0" description = "Functools like those found in stdlib" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "(python_version <= \"3.11\" or python_version >= \"3.12\") and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\")" files = [ {file = "jaraco.functools-4.1.0-py3-none-any.whl", hash = "sha256:ad159f13428bc4acbf5541ad6dec511f91573b90fba04df61dafa2a1231cf649"}, {file = "jaraco_functools-4.1.0.tar.gz", hash = "sha256:70f7e0e2ae076498e212562325e805204fc092d7b4c17e0e86c959e249701a9d"}, @@ -914,6 +992,8 @@ version = "0.8.0" description = "Low-level, pure Python DBus protocol wrapper." optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "(platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" and (python_version <= \"3.11\" or python_version >= \"3.12\")" files = [ {file = "jeepney-0.8.0-py3-none-any.whl", hash = "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755"}, {file = "jeepney-0.8.0.tar.gz", hash = "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806"}, @@ -929,6 +1009,8 @@ version = "3.1.5" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"}, {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"}, @@ -946,6 +1028,8 @@ version = "25.6.0" description = "Store and access your passwords safely." optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "(python_version <= \"3.11\" or python_version >= \"3.12\") and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\")" files = [ {file = "keyring-25.6.0-py3-none-any.whl", hash = "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd"}, {file = "keyring-25.6.0.tar.gz", hash = "sha256:0b39998aa941431eb3d9b0d4b2460bc773b9df6fed7621c2dfb291a7e0187a66"}, @@ -975,6 +1059,8 @@ version = "0.4" description = "Makes it easy to load subpackages and functions on demand." optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "lazy_loader-0.4-py3-none-any.whl", hash = "sha256:342aa8e14d543a154047afb4ba8ef17f5563baad3fc610d7b15b213b0f119efc"}, {file = "lazy_loader-0.4.tar.gz", hash = "sha256:47c75182589b91a4e1a85a136c074285a5ad4d9f39c63e0d7fb76391c4574cd1"}, @@ -994,6 +1080,8 @@ version = "1.3.8" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "Mako-1.3.8-py3-none-any.whl", hash = "sha256:42f48953c7eb91332040ff567eb7eea69b22e7a4affbc5ba8e845e8f730f6627"}, {file = "mako-1.3.8.tar.gz", hash = "sha256:577b97e414580d3e088d47c2dbbe9594aa7a5146ed2875d4dfa9075af2dd3cc8"}, @@ -1013,6 +1101,8 @@ version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, @@ -1037,6 +1127,8 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -1107,6 +1199,8 @@ version = "0.1.2" description = "Markdown URL utilities" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -1118,6 +1212,8 @@ version = "10.6.0" description = "More routines for operating on iterables, beyond itertools" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "(python_version <= \"3.11\" or python_version >= \"3.12\") and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\")" files = [ {file = "more-itertools-10.6.0.tar.gz", hash = "sha256:2cd7fad1009c31cc9fb6a035108509e6547547a7a738374f10bd49a09eb3ee3b"}, {file = "more_itertools-10.6.0-py3-none-any.whl", hash = "sha256:6eb054cb4b6db1473f6e15fcc676a08e4732548acd47c708f0e179c2c7c01e89"}, @@ -1129,6 +1225,8 @@ version = "0.2.20" description = "Python binding to Ammonia HTML sanitizer Rust crate" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "nh3-0.2.20-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e1061a4ab6681f6bdf72b110eea0c4e1379d57c9de937db3be4202f7ad6043db"}, {file = "nh3-0.2.20-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb4254b1dac4a1ee49919a5b3f1caf9803ea8dada1816d9e8289e63d3cd0dd9a"}, @@ -1162,6 +1260,8 @@ version = "1.9.1" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, @@ -1173,6 +1273,8 @@ version = "2.2.2" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "numpy-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7079129b64cb78bdc8d611d1fd7e8002c0a2565da6a47c4df8062349fee90e3e"}, {file = "numpy-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ec6c689c61df613b783aeb21f945c4cbe6c51c28cb70aae8430577ab39f163e"}, @@ -1237,6 +1339,8 @@ version = "1.3.0.post0" description = "Capture the outcome of Python function calls." optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"}, {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"}, @@ -1251,6 +1355,8 @@ version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, @@ -1262,6 +1368,8 @@ version = "2.2.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5"}, {file = "pandas-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:381175499d3802cde0eabbaf6324cce0c4f5d52ca6f8c377c29ad442f50f6348"}, @@ -1348,6 +1456,8 @@ version = "11.1.0" description = "Python Imaging Library (Fork)" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pillow-11.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:e1abe69aca89514737465752b4bcaf8016de61b3be1397a8fc260ba33321b3a8"}, {file = "pillow-11.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c640e5a06869c75994624551f45e5506e4256562ead981cce820d5ab39ae2192"}, @@ -1436,6 +1546,8 @@ version = "24.3.1" description = "The PyPA recommended tool for installing Python packages." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pip-24.3.1-py3-none-any.whl", hash = "sha256:3790624780082365f47549d032f3770eeb2b1e8bd1f7b2e02dace1afa361b4ed"}, {file = "pip-24.3.1.tar.gz", hash = "sha256:ebcb60557f2aefabc2e0f918751cd24ea0d56d8ec5445fe1807f1d2109660b99"}, @@ -1447,6 +1559,8 @@ version = "2.16.2" description = "Command line utility to show dependency tree of packages." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pipdeptree-2.16.2-py3-none-any.whl", hash = "sha256:4b60a20f632aa3449880141d1cd0bc99cb5f93ed46d54d689fd1c9b95f0e53d0"}, {file = "pipdeptree-2.16.2.tar.gz", hash = "sha256:96ecde8e6f40c95998491a385e4af56d387f94ff7d3b8f209aa34982a721bc43"}, @@ -1465,6 +1579,8 @@ version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -1481,6 +1597,8 @@ version = "1.49.1" description = "A high-level API to automate web browsers" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "playwright-1.49.1-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:1041ffb45a0d0bc44d698d3a5aa3ac4b67c9bd03540da43a0b70616ad52592b8"}, {file = "playwright-1.49.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9f38ed3d0c1f4e0a6d1c92e73dd9a61f8855133249d6f0cec28648d38a7137be"}, @@ -1501,6 +1619,8 @@ version = "5.24.1" description = "An open-source, interactive data visualization library for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "plotly-5.24.1-py3-none-any.whl", hash = "sha256:f67073a1e637eb0dc3e46324d9d51e2fe76e9727c892dde64ddf1e1b51f29089"}, {file = "plotly-5.24.1.tar.gz", hash = "sha256:dbc8ac8339d248a4bcc36e08a5659bacfe1b079390b8953533f4eb22169b4bae"}, @@ -1516,6 +1636,8 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -1531,6 +1653,8 @@ version = "4.1.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pre_commit-4.1.0-py2.py3-none-any.whl", hash = "sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b"}, {file = "pre_commit-4.1.0.tar.gz", hash = "sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4"}, @@ -1549,6 +1673,8 @@ version = "6.1.1" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "psutil-6.1.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9ccc4316f24409159897799b83004cb1e24f9819b0dcf9c0b68bdcb6cefee6a8"}, {file = "psutil-6.1.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ca9609c77ea3b8481ab005da74ed894035936223422dc591d6772b147421f777"}, @@ -1579,6 +1705,8 @@ version = "9.0.0" description = "Get CPU info with pure Python" optional = false python-versions = "*" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690"}, {file = "py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5"}, @@ -1590,10 +1718,12 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] +markers = {main = "(platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" and platform_python_implementation != \"PyPy\" and (python_version <= \"3.11\" or python_version >= \"3.12\")", dev = "os_name == \"nt\" and implementation_name != \"pypy\" and (python_version <= \"3.11\" or python_version >= \"3.12\")"} [[package]] name = "pydantic" @@ -1601,6 +1731,8 @@ version = "2.10.5" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"}, {file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"}, @@ -1621,6 +1753,8 @@ version = "2.27.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, @@ -1733,6 +1867,8 @@ version = "12.0.0" description = "A rough port of Node.js's EventEmitter to Python with a few tricks of its own" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pyee-12.0.0-py3-none-any.whl", hash = "sha256:7b14b74320600049ccc7d0e0b1becd3b4bd0a03c745758225e31a59f4095c990"}, {file = "pyee-12.0.0.tar.gz", hash = "sha256:c480603f4aa2927d4766eb41fa82793fe60a82cbfdb8d688e0d08c55a534e145"}, @@ -1750,6 +1886,8 @@ version = "2.19.1" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, @@ -1764,6 +1902,8 @@ version = "1.2.0" description = "Wrappers to call pyproject.toml-based build backend hooks." optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913"}, {file = "pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8"}, @@ -1775,6 +1915,8 @@ version = "1.1.334" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pyright-1.1.334-py3-none-any.whl", hash = "sha256:dcb13e8358e021189672c4d6ebcad192ab061e4c7225036973ec493183c6da68"}, {file = "pyright-1.1.334.tar.gz", hash = "sha256:3adaf10f1f4209575dc022f9c897f7ef024639b7ea5b3cbe49302147e6949cd4"}, @@ -1793,6 +1935,8 @@ version = "1.7.1" description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"}, {file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"}, @@ -1805,6 +1949,8 @@ version = "8.3.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, @@ -1827,6 +1973,8 @@ version = "0.25.2" description = "Pytest support for asyncio" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pytest_asyncio-0.25.2-py3-none-any.whl", hash = "sha256:0d0bb693f7b99da304a0634afc0a4b19e49d5e0de2d670f38dc4bfa5727c5075"}, {file = "pytest_asyncio-0.25.2.tar.gz", hash = "sha256:3f8ef9a98f45948ea91a0ed3dc4268b5326c0e7bce73892acc654df4262ad45f"}, @@ -1845,6 +1993,8 @@ version = "2.1.0" description = "pytest plugin for URL based testing" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pytest_base_url-2.1.0-py3-none-any.whl", hash = "sha256:3ad15611778764d451927b2a53240c1a7a591b521ea44cebfe45849d2d2812e6"}, {file = "pytest_base_url-2.1.0.tar.gz", hash = "sha256:02748589a54f9e63fcbe62301d6b0496da0d10231b753e950c63e03aee745d45"}, @@ -1863,6 +2013,8 @@ version = "5.1.0" description = "A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pytest-benchmark-5.1.0.tar.gz", hash = "sha256:9ea661cdc292e8231f7cd4c10b0319e56a2118e2c09d9f50e1b3d150d2aca105"}, {file = "pytest_benchmark-5.1.0-py3-none-any.whl", hash = "sha256:922de2dfa3033c227c96da942d1878191afa135a29485fb942e85dff1c592c89"}, @@ -1883,6 +2035,8 @@ version = "6.0.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0"}, {file = "pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35"}, @@ -1901,6 +2055,8 @@ version = "3.14.0" description = "Thin-wrapper around the mock package for easier use with pytest" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, @@ -1918,6 +2074,8 @@ version = "0.6.2" description = "A pytest wrapper with fixtures for Playwright to automate web browsers" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pytest_playwright-0.6.2-py3-none-any.whl", hash = "sha256:0eff73bebe497b0158befed91e2f5fe94cfa17181f8b3acf575beed84e7e9043"}, {file = "pytest_playwright-0.6.2.tar.gz", hash = "sha256:ff4054b19aa05df096ac6f74f0572591566aaf0f6d97f6cb9674db8a4d4ed06c"}, @@ -1935,6 +2093,8 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1949,6 +2109,8 @@ version = "4.11.2" description = "Engine.IO server and client for Python" optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "python_engineio-4.11.2-py3-none-any.whl", hash = "sha256:f0971ac4c65accc489154fe12efd88f53ca8caf04754c46a66e85f5102ef22ad"}, {file = "python_engineio-4.11.2.tar.gz", hash = "sha256:145bb0daceb904b4bb2d3eb2d93f7dbb7bb87a6a0c4f20a94cc8654dec977129"}, @@ -1968,6 +2130,8 @@ version = "0.0.20" description = "A streaming multipart parser for Python" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104"}, {file = "python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13"}, @@ -1979,6 +2143,8 @@ version = "8.0.4" description = "A Python slugify application that also handles Unicode" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"}, {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"}, @@ -1996,6 +2162,8 @@ version = "5.12.1" description = "Socket.IO server and client for Python" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "python_socketio-5.12.1-py3-none-any.whl", hash = "sha256:24a0ea7cfff0e021eb28c68edbf7914ee4111bdf030b95e4d250c4dc9af7a386"}, {file = "python_socketio-5.12.1.tar.gz", hash = "sha256:0299ff1f470b676c09c1bfab1dead25405077d227b2c13cf217a34dadc68ba9c"}, @@ -2016,6 +2184,8 @@ version = "2024.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, @@ -2027,6 +2197,8 @@ version = "0.2.3" description = "A (partial) reimplementation of pywin32 using ctypes/cffi" optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "(platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"win32\" and (python_version <= \"3.11\" or python_version >= \"3.12\")" files = [ {file = "pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755"}, {file = "pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8"}, @@ -2038,6 +2210,8 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -2100,6 +2274,8 @@ version = "44.0" description = "readme_renderer is a library for rendering readme descriptions for Warehouse" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "readme_renderer-44.0-py3-none-any.whl", hash = "sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151"}, {file = "readme_renderer-44.0.tar.gz", hash = "sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1"}, @@ -2119,6 +2295,8 @@ version = "5.2.1" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4"}, {file = "redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f"}, @@ -2137,6 +2315,8 @@ version = "0.1.32" description = "Reflex Hosting CLI" optional = false python-versions = "<4.0,>=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "reflex_hosting_cli-0.1.32-py3-none-any.whl", hash = "sha256:86b4222f3e99d949a209be7de8c457ededebc1f12a721ee6669c6c35fdecc508"}, {file = "reflex_hosting_cli-0.1.32.tar.gz", hash = "sha256:0b8e4b4b30d9261bf6d720265f1c428b2840bb630896e60a1a2faa095901ed59"}, @@ -2161,6 +2341,8 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -2182,6 +2364,8 @@ version = "1.0.0" description = "A utility belt for advanced users of python-requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, @@ -2196,6 +2380,8 @@ version = "2.0.0" description = "Validating URI References per RFC 3986" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd"}, {file = "rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c"}, @@ -2210,6 +2396,8 @@ version = "13.9.4" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, @@ -2229,6 +2417,8 @@ version = "0.8.2" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "ruff-0.8.2-py3-none-linux_armv6l.whl", hash = "sha256:c49ab4da37e7c457105aadfd2725e24305ff9bc908487a9bf8d548c6dad8bb3d"}, {file = "ruff-0.8.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ec016beb69ac16be416c435828be702ee694c0d722505f9c1f35e1b9c0cc1bf5"}, @@ -2256,6 +2446,8 @@ version = "3.3.3" description = "Python bindings to FreeDesktop.org Secret Service API" optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "(platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" and (python_version <= \"3.11\" or python_version >= \"3.12\")" files = [ {file = "SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99"}, {file = "SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77"}, @@ -2271,6 +2463,8 @@ version = "4.28.0" description = "Official Python bindings for Selenium WebDriver" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "selenium-4.28.0-py3-none-any.whl", hash = "sha256:3d6a2e8e1b850a1078884ea19f4e011ecdc12263434d87a0b78769836fb82dd8"}, {file = "selenium-4.28.0.tar.gz", hash = "sha256:a9fae6eef48d470a1b0c6e45185d96f0dafb025e8da4b346cc41e4da3ac54fa0"}, @@ -2290,6 +2484,8 @@ version = "75.8.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "setuptools-75.8.0-py3-none-any.whl", hash = "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3"}, {file = "setuptools-75.8.0.tar.gz", hash = "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6"}, @@ -2310,6 +2506,8 @@ version = "1.5.4" description = "Tool to Detect Surrounding Shell" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, @@ -2321,6 +2519,8 @@ version = "1.1.0" description = "Simple WebSocket server and client for Python" optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "simple_websocket-1.1.0-py3-none-any.whl", hash = "sha256:4af6069630a38ed6c561010f0e11a5bc0d4ca569b36306eb257cd9a192497c8c"}, {file = "simple_websocket-1.1.0.tar.gz", hash = "sha256:7939234e7aa067c534abdab3a9ed933ec9ce4691b0713c78acb195560aa52ae4"}, @@ -2339,6 +2539,8 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -2350,6 +2552,8 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -2361,6 +2565,8 @@ version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" optional = false python-versions = "*" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, @@ -2372,6 +2578,8 @@ version = "2.0.37" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "SQLAlchemy-2.0.37-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da36c3b0e891808a7542c5c89f224520b9a16c7f5e4d6a1156955605e54aef0e"}, {file = "SQLAlchemy-2.0.37-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e7402ff96e2b073a98ef6d6142796426d705addd27b9d26c3b32dbaa06d7d069"}, @@ -2467,6 +2675,8 @@ version = "0.0.22" description = "SQLModel, SQL databases in Python, designed for simplicity, compatibility, and robustness." optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "sqlmodel-0.0.22-py3-none-any.whl", hash = "sha256:a1ed13e28a1f4057cbf4ff6cdb4fc09e85702621d3259ba17b3c230bfb2f941b"}, {file = "sqlmodel-0.0.22.tar.gz", hash = "sha256:7d37c882a30c43464d143e35e9ecaf945d88035e20117bf5ec2834a23cbe505e"}, @@ -2482,6 +2692,8 @@ version = "0.41.3" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "starlette-0.41.3-py3-none-any.whl", hash = "sha256:44cedb2b7c77a9de33a8b74b2b90e9f50d11fcf25d8270ea525ad71a25374ff7"}, {file = "starlette-0.41.3.tar.gz", hash = "sha256:0e4ab3d16522a255be6b28260b938eae2482f98ce5cc934cb08dce8dc3ba5835"}, @@ -2499,6 +2711,8 @@ version = "0.14.1" description = "Fast, beautiful and extensible administrative interface framework for Starlette/FastApi applications" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "starlette_admin-0.14.1-py3-none-any.whl", hash = "sha256:5b6260d7ed3db455585852d669feb7ed9a8c5f9a1e3d48d21a52912ec37e18f9"}, {file = "starlette_admin-0.14.1.tar.gz", hash = "sha256:45e2baa3b9a8deec7a6e8ca9295123f648bb0d2070abe68f27193c6d5e32cc38"}, @@ -2522,6 +2736,8 @@ version = "0.9.0" description = "Pretty-print tabular data" optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, @@ -2536,6 +2752,8 @@ version = "9.0.0" description = "Retry code until it succeeds" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "tenacity-9.0.0-py3-none-any.whl", hash = "sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539"}, {file = "tenacity-9.0.0.tar.gz", hash = "sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b"}, @@ -2551,6 +2769,8 @@ version = "1.3" description = "The most basic Text::Unidecode port" optional = false python-versions = "*" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, @@ -2562,6 +2782,8 @@ version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, @@ -2573,6 +2795,8 @@ version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version < \"3.11\"" files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -2614,6 +2838,8 @@ version = "0.13.2" description = "Style preserving TOML library" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, @@ -2625,6 +2851,8 @@ version = "0.28.0" description = "A friendly Python library for async concurrency and I/O" optional = false python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "trio-0.28.0-py3-none-any.whl", hash = "sha256:56d58977acc1635735a96581ec70513cc781b8b6decd299c487d3be2a721cd94"}, {file = "trio-0.28.0.tar.gz", hash = "sha256:4e547896fe9e8a5658e54e4c7c5fa1db748cbbbaa7c965e7d40505b928c73c05"}, @@ -2645,6 +2873,8 @@ version = "0.11.1" description = "WebSocket library for Trio" optional = false python-versions = ">=3.7" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f"}, {file = "trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"}, @@ -2661,6 +2891,8 @@ version = "6.1.0" description = "Collection of utilities for publishing packages on PyPI" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "twine-6.1.0-py3-none-any.whl", hash = "sha256:a47f973caf122930bf0fbbf17f80b83bc1602c9ce393c7845f289a3001dc5384"}, {file = "twine-6.1.0.tar.gz", hash = "sha256:be324f6272eff91d07ee93f251edf232fc647935dd585ac003539b42404a8dbd"}, @@ -2686,6 +2918,8 @@ version = "0.15.1" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." optional = false python-versions = ">=3.7" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "typer-0.15.1-py3-none-any.whl", hash = "sha256:7994fb7b8155b64d3402518560648446072864beefd44aa2dc36972a5972e847"}, {file = "typer-0.15.1.tar.gz", hash = "sha256:a0588c0a7fa68a1978a069818657778f86abe6ff5ea6abf472f940a08bfe4f0a"}, @@ -2703,6 +2937,8 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -2714,6 +2950,8 @@ version = "2025.1" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639"}, {file = "tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694"}, @@ -2725,6 +2963,8 @@ version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, @@ -2745,6 +2985,8 @@ version = "0.34.0" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4"}, {file = "uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9"}, @@ -2764,6 +3006,8 @@ version = "20.29.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779"}, {file = "virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35"}, @@ -2784,6 +3028,8 @@ version = "1.8.0" description = "WebSocket client for Python with low level API options" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, @@ -2800,6 +3046,8 @@ version = "14.2" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "websockets-14.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e8179f95323b9ab1c11723e5d91a89403903f7b001828161b480a7810b334885"}, {file = "websockets-14.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0d8c3e2cdb38f31d8bd7d9d28908005f6fa9def3324edb9bf336d7e4266fd397"}, @@ -2878,6 +3126,8 @@ version = "0.45.1" description = "A built-package format for Python" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248"}, {file = "wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729"}, @@ -2892,6 +3142,8 @@ version = "1.17.2" description = "Module for decorators, wrappers and monkey patching." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"}, {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"}, @@ -2980,6 +3232,8 @@ version = "1.2.0" description = "WebSockets state-machine based protocol implementation" optional = false python-versions = ">=3.7.0" +groups = ["main", "dev"] +markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, @@ -2994,6 +3248,8 @@ version = "3.21.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.9" +groups = ["main"] +markers = "(platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and python_version <= \"3.11\" or python_full_version < \"3.10.2\"" files = [ {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, @@ -3008,6 +3264,6 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", type = ["pytest-mypy"] [metadata] -lock-version = "2.0" -python-versions = "^3.10" -content-hash = "fe74f0936bfcc691653b16771a276b2f7d7469c578d81a52277a36f9ad398edb" +lock-version = "2.1" +python-versions = ">=3.10, <4.0" +content-hash = "376707066a00c43aef555c6db2ccb0ddfde0ee9011e8f20110d728fb723f1662" diff --git a/pyproject.toml b/pyproject.toml index 03580cd0f..d19d1a0ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ keywords = ["web", "framework"] classifiers = ["Development Status :: 4 - Beta"] [tool.poetry.dependencies] -python = "^3.10" +python = ">=3.10, <4.0" fastapi = ">=0.96.0,!=0.111.0,!=0.111.1" gunicorn = ">=20.1.0,<24.0" jinja2 = ">=3.1.2,<4.0" @@ -82,7 +82,7 @@ build-backend = "poetry.core.masonry.api" [tool.pyright] [tool.ruff] -target-version = "py39" +target-version = "py310" output-format = "concise" lint.isort.split-on-trailing-comma = false lint.select = ["B", "C4", "D", "E", "ERA", "F", "FURB", "I", "N", "PERF", "PTH", "RUF", "SIM", "T", "TRY", "W"] diff --git a/reflex/app.py b/reflex/app.py index d432925ab..2e9765d21 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -672,7 +672,10 @@ class App(MiddlewareMixin, LifespanMixin): for route in self._pages: replaced_route = replace_brackets_with_keywords(route) for rw, r, nr in zip( - replaced_route.split("/"), route.split("/"), new_route.split("/") + replaced_route.split("/"), + route.split("/"), + new_route.split("/"), + strict=False, ): if rw in segments and r != nr: # If the slugs in the segments of both routes are not the same, then the route is invalid @@ -1039,7 +1042,7 @@ class App(MiddlewareMixin, LifespanMixin): max_workers=environment.REFLEX_COMPILE_THREADS.get() or None ) - for route, component in zip(self._pages, page_components): + for route, component in zip(self._pages, page_components, strict=True): ExecutorSafeFunctions.COMPONENTS[route] = component ExecutorSafeFunctions.STATE = self._state @@ -1236,6 +1239,7 @@ class App(MiddlewareMixin, LifespanMixin): frontend_arg_spec, backend_arg_spec, ], + strict=True, ): if hasattr(handler_fn, "__name__"): _fn_name = handler_fn.__name__ diff --git a/reflex/components/core/breakpoints.py b/reflex/components/core/breakpoints.py index 25396ecd9..9a8ef1556 100644 --- a/reflex/components/core/breakpoints.py +++ b/reflex/components/core/breakpoints.py @@ -82,7 +82,9 @@ class Breakpoints(Dict[K, V]): return Breakpoints( { k: v - for k, v in zip(["initial", *breakpoint_names], thresholds) + for k, v in zip( + ["initial", *breakpoint_names], thresholds, strict=True + ) if v is not None } ) diff --git a/reflex/event.py b/reflex/event.py index 6da65c366..96c2c30b9 100644 --- a/reflex/event.py +++ b/reflex/event.py @@ -243,7 +243,7 @@ class EventHandler(EventActionsMixin): raise EventHandlerTypeError( f"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}." ) from e - payload = tuple(zip(fn_args, values)) + payload = tuple(zip(fn_args, values, strict=False)) # Return the event spec. return EventSpec( @@ -337,7 +337,7 @@ class EventSpec(EventActionsMixin): raise EventHandlerTypeError( f"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}." ) from e - new_payload = tuple(zip(fn_args, values)) + new_payload = tuple(zip(fn_args, values, strict=False)) return self.with_args(self.args + new_payload) diff --git a/reflex/state.py b/reflex/state.py index 40afcbc79..be3deda78 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -1434,6 +1434,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): for part1, part2 in zip( cls.get_full_name().split("."), other.get_full_name().split("."), + strict=True, ): if part1 != part2: break diff --git a/reflex/utils/types.py b/reflex/utils/types.py index ac30342e2..0b3ec7e9f 100644 --- a/reflex/utils/types.py +++ b/reflex/utils/types.py @@ -605,7 +605,9 @@ def _isinstance(obj: Any, cls: GenericType, nested: bool = False) -> bool: return ( isinstance(obj, tuple) and len(obj) == len(args) - and all(_isinstance(item, arg) for item, arg in zip(obj, args)) + and all( + _isinstance(item, arg) for item, arg in zip(obj, args, strict=True) + ) ) if origin in (dict, Breakpoints): return isinstance(obj, dict) and all( @@ -808,7 +810,7 @@ def validate_parameter_literals(func): annotations = {param[0]: param[1].annotation for param in func_params} # validate args - for param, arg in zip(annotations, args): + for param, arg in zip(annotations, args, strict=False): if annotations[param] is inspect.Parameter.empty: continue validate_literal(param, arg, annotations[param], func.__name__) @@ -906,6 +908,8 @@ def typehint_issubclass(possible_subclass: Any, possible_superclass: Any) -> boo # It also ignores when the length of the arguments is different return all( typehint_issubclass(provided_arg, accepted_arg) - for provided_arg, accepted_arg in zip(provided_args, accepted_args) + for provided_arg, accepted_arg in zip( + provided_args, accepted_args, strict=False + ) if accepted_arg is not Any ) diff --git a/reflex/vars/base.py b/reflex/vars/base.py index f6359166f..a3b3059e9 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -2721,7 +2721,7 @@ def generic_type_to_actual_type_map( # call recursively for nested generic types and merge the results return { k: v - for generic_arg, actual_arg in zip(generic_args, actual_args) + for generic_arg, actual_arg in zip(generic_args, actual_args, strict=True) for k, v in generic_type_to_actual_type_map(generic_arg, actual_arg).items() } diff --git a/tests/units/compiler/test_compiler.py b/tests/units/compiler/test_compiler.py index 22f5c8483..25c351c01 100644 --- a/tests/units/compiler/test_compiler.py +++ b/tests/units/compiler/test_compiler.py @@ -100,7 +100,7 @@ def test_compile_imports(import_dict: ParsedImportDict, test_dicts: List[dict]): test_dicts: The expected output. """ imports = utils.compile_imports(import_dict) - for import_dict, test_dict in zip(imports, test_dicts): + for import_dict, test_dict in zip(imports, test_dicts, strict=True): assert import_dict["lib"] == test_dict["lib"] assert import_dict["default"] == test_dict["default"] assert sorted(import_dict["rest"]) == test_dict["rest"] # type: ignore diff --git a/tests/units/components/test_component.py b/tests/units/components/test_component.py index 5bad24499..6ea459142 100644 --- a/tests/units/components/test_component.py +++ b/tests/units/components/test_component.py @@ -1446,6 +1446,7 @@ def test_get_vars(component, exp_vars): for comp_var, exp_var in zip( comp_vars, sorted(exp_vars, key=lambda v: v._js_expr), + strict=True, ): assert comp_var.equals(exp_var) @@ -1827,6 +1828,7 @@ def test_custom_component_declare_event_handlers_in_fields(): for v1, v2 in zip( parse_args_spec(test_triggers[trigger_name]), parse_args_spec(custom_triggers[trigger_name]), + strict=True, ): assert v1.equals(v2) diff --git a/tests/units/test_var.py b/tests/units/test_var.py index 88f05a53e..51b0d9a2b 100644 --- a/tests/units/test_var.py +++ b/tests/units/test_var.py @@ -188,6 +188,7 @@ def ChildWithRuntimeOnlyVar(StateWithRuntimeOnlyVar): "state.local", "local2", ], + strict=True, ), ) def test_full_name(prop, expected): @@ -205,6 +206,7 @@ def test_full_name(prop, expected): zip( test_vars, ["prop1", "key", "state.value", "state.local", "local2"], + strict=True, ), ) def test_str(prop, expected): @@ -251,6 +253,7 @@ def test_default_value(prop: Var, expected): "state.set_local", "set_local2", ], + strict=True, ), ) def test_get_setter(prop: Var, expected): From 64fb78ac5e3310fa4783739f9054468b5913cf06 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Tue, 28 Jan 2025 11:46:00 -0800 Subject: [PATCH 04/13] fix subprotocol for granian (#4698) * fix subprotocol for granian * use scope subprotocols * use subprotocols or headers * separate the logic --- reflex/app.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/reflex/app.py b/reflex/app.py index 2e9765d21..20c01cba6 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -27,6 +27,7 @@ from typing import ( Dict, Generic, List, + MutableMapping, Optional, Set, Type, @@ -410,20 +411,25 @@ class App(MiddlewareMixin, LifespanMixin): def __init__(self, app): self.app = app - async def __call__(self, scope, receive, send): + async def __call__( + self, scope: MutableMapping[str, Any], receive, send + ): original_send = send async def modified_send(message): - headers = dict(scope["headers"]) - protocol_key = b"sec-websocket-protocol" - if ( - message["type"] == "websocket.accept" - and protocol_key in headers - ): - message["headers"] = [ - *message.get("headers", []), - (b"sec-websocket-protocol", headers[protocol_key]), - ] + if message["type"] == "websocket.accept": + if scope.get("subprotocols"): + # The following *does* say "subprotocol" instead of "subprotocols", intentionally. + message["subprotocol"] = scope["subprotocols"][0] + + headers = dict(message.get("headers", [])) + header_key = b"sec-websocket-protocol" + if subprotocol := headers.get(header_key): + message["headers"] = [ + *message.get("headers", []), + (header_key, subprotocol), + ] + return await original_send(message) return await self.app(scope, receive, modified_send) From 42e6dfa40d428c81cd1dd724a7e6cb463f3f63b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Tue, 28 Jan 2025 22:11:05 +0100 Subject: [PATCH 05/13] enable PGH, bump pyright and fix all #type: ignore (#4699) * enable PGH, bump pyright and fix all #type: ignore * relock poetry file * ignore incompatible override * fix varop tests * ignore missing imports * fix * fix stuff * fix tests * rechange tests * relock with poetry 2.0 --- .pre-commit-config.yaml | 2 +- .../test_benchmark_compile_components.py | 20 +- benchmarks/test_benchmark_compile_pages.py | 26 +-- poetry.lock | 192 ++++-------------- pyproject.toml | 7 +- reflex/__init__.pyi | 2 +- reflex/app.py | 6 +- reflex/app_mixins/lifespan.py | 10 +- reflex/app_mixins/middleware.py | 12 +- reflex/base.py | 12 +- reflex/compiler/utils.py | 6 +- reflex/components/base/bare.py | 2 +- reflex/components/base/meta.py | 4 +- reflex/components/component.py | 18 +- reflex/components/core/banner.py | 8 +- reflex/components/core/cond.py | 17 +- reflex/components/core/debounce.py | 2 +- reflex/components/core/match.py | 8 +- reflex/components/core/upload.py | 2 +- reflex/components/datadisplay/code.py | 2 +- reflex/components/datadisplay/dataeditor.py | 6 +- .../datadisplay/shiki_code_block.py | 11 +- reflex/components/el/constants/reflex.py | 2 +- reflex/components/el/elements/forms.py | 4 +- reflex/components/markdown/markdown.py | 10 +- reflex/components/moment/moment.py | 4 +- reflex/components/next/link.py | 2 +- reflex/components/plotly/plotly.py | 8 +- reflex/components/props.py | 4 +- reflex/components/radix/__init__.pyi | 2 +- reflex/components/radix/primitives/drawer.py | 2 +- .../components/radix/primitives/progress.py | 2 +- reflex/components/radix/primitives/slider.py | 2 +- reflex/components/radix/themes/color_mode.py | 4 +- .../radix/themes/components/radio_group.py | 2 +- .../radix/themes/components/text_field.py | 2 +- .../radix/themes/layout/__init__.pyi | 2 +- reflex/components/radix/themes/layout/list.py | 2 +- .../components/radix/themes/layout/stack.py | 4 +- .../radix/themes/typography/link.py | 2 +- .../radix/themes/typography/text.py | 4 +- .../components/react_player/react_player.py | 2 +- reflex/components/recharts/charts.py | 22 +- reflex/components/recharts/polar.py | 2 +- reflex/components/sonner/toast.py | 8 +- reflex/components/tags/iter_tag.py | 6 +- reflex/config.py | 6 +- reflex/custom_components/custom_components.py | 2 +- reflex/event.py | 50 ++--- reflex/experimental/client_state.py | 4 +- reflex/experimental/layout.py | 10 +- reflex/model.py | 4 +- reflex/reflex.py | 4 +- reflex/state.py | 28 +-- reflex/style.py | 2 +- reflex/testing.py | 36 ++-- reflex/utils/compat.py | 8 +- reflex/utils/console.py | 6 +- reflex/utils/exec.py | 26 ++- reflex/utils/format.py | 10 +- reflex/utils/imports.py | 2 +- reflex/utils/prerequisites.py | 10 +- reflex/utils/processes.py | 8 +- reflex/utils/pyi_generator.py | 36 ++-- reflex/utils/serializers.py | 2 +- reflex/utils/types.py | 26 ++- reflex/vars/base.py | 56 ++--- reflex/vars/datetime.py | 8 +- reflex/vars/function.py | 4 +- reflex/vars/number.py | 34 ++-- reflex/vars/object.py | 12 +- reflex/vars/sequence.py | 34 ++-- tests/integration/test_background_task.py | 10 +- tests/integration/test_component_state.py | 6 +- tests/integration/test_connection_banner.py | 2 +- tests/integration/test_deploy_url.py | 2 +- tests/integration/test_dynamic_routes.py | 22 +- tests/integration/test_event_actions.py | 30 +-- tests/integration/test_event_chain.py | 46 ++--- tests/integration/test_exception_handlers.py | 4 +- tests/integration/test_input.py | 4 +- tests/integration/test_lifespan.py | 6 +- tests/integration/test_login_flow.py | 4 +- tests/integration/test_media.py | 4 +- tests/integration/test_state_inheritance.py | 12 +- tests/integration/test_upload.py | 8 +- tests/integration/test_var_operations.py | 60 +++--- .../tests_playwright/test_appearance.py | 8 +- .../test_datetime_operations.py | 2 +- .../tests_playwright/test_link_hover.py | 2 +- tests/units/compiler/test_compiler.py | 10 +- tests/units/components/core/test_colors.py | 24 +-- tests/units/components/core/test_cond.py | 8 +- tests/units/components/core/test_html.py | 6 +- tests/units/components/core/test_match.py | 4 +- tests/units/components/core/test_upload.py | 10 +- .../units/components/datadisplay/test_code.py | 2 +- .../components/datadisplay/test_datatable.py | 6 +- .../components/datadisplay/test_shiki_code.py | 10 +- tests/units/components/forms/test_form.py | 2 +- tests/units/components/media/test_image.py | 12 +- tests/units/components/test_component.py | 52 ++--- .../components/typography/test_markdown.py | 10 +- tests/units/conftest.py | 10 +- tests/units/states/mutation.py | 2 +- tests/units/test_app.py | 66 +++--- tests/units/test_config.py | 4 +- tests/units/test_event.py | 8 +- tests/units/test_health_endpoint.py | 4 +- tests/units/test_model.py | 14 +- tests/units/test_prerequisites.py | 2 +- tests/units/test_sqlalchemy.py | 8 +- tests/units/test_state.py | 114 +++++------ tests/units/test_style.py | 8 +- tests/units/test_var.py | 12 +- tests/units/utils/test_format.py | 6 +- tests/units/utils/test_utils.py | 6 +- 117 files changed, 731 insertions(+), 828 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 54d8f3d72..dbe069ae8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,7 +28,7 @@ repos: entry: python3 scripts/make_pyi.py - repo: https://github.com/RobertCraigie/pyright-python - rev: v1.1.334 + rev: v1.1.392 hooks: - id: pyright args: [reflex, tests] diff --git a/benchmarks/test_benchmark_compile_components.py b/benchmarks/test_benchmark_compile_components.py index ba7e9c571..9bcfbf85b 100644 --- a/benchmarks/test_benchmark_compile_components.py +++ b/benchmarks/test_benchmark_compile_components.py @@ -34,13 +34,13 @@ def render_component(num: int): rx.box( rx.accordion.root( rx.accordion.item( - header="Full Ingredients", # type: ignore - content="Yes. It's built with accessibility in mind.", # type: ignore + header="Full Ingredients", + content="Yes. It's built with accessibility in mind.", font_size="3em", ), rx.accordion.item( - header="Applications", # type: ignore - content="Yes. It's unstyled by default, giving you freedom over the look and feel.", # type: ignore + header="Applications", + content="Yes. It's unstyled by default, giving you freedom over the look and feel.", ), collapsible=True, variant="ghost", @@ -166,9 +166,9 @@ def app_with_10_components( root=root, app_source=functools.partial( AppWithTenComponentsOnePage, - render_component=render_component, # type: ignore + render_component=render_component, # pyright: ignore [reportCallIssue] ), - ) # type: ignore + ) @pytest.fixture(scope="session") @@ -189,9 +189,9 @@ def app_with_100_components( root=root, app_source=functools.partial( AppWithHundredComponentOnePage, - render_component=render_component, # type: ignore + render_component=render_component, # pyright: ignore [reportCallIssue] ), - ) # type: ignore + ) @pytest.fixture(scope="session") @@ -212,9 +212,9 @@ def app_with_1000_components( root=root, app_source=functools.partial( AppWithThousandComponentsOnePage, - render_component=render_component, # type: ignore + render_component=render_component, # pyright: ignore [reportCallIssue] ), - ) # type: ignore + ) @pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON) diff --git a/benchmarks/test_benchmark_compile_pages.py b/benchmarks/test_benchmark_compile_pages.py index a5c85810e..149fc6130 100644 --- a/benchmarks/test_benchmark_compile_pages.py +++ b/benchmarks/test_benchmark_compile_pages.py @@ -28,7 +28,7 @@ def render_multiple_pages(app, num: int): """ from typing import Tuple - from rxconfig import config # type: ignore + from rxconfig import config # pyright: ignore [reportMissingImports] import reflex as rx @@ -74,13 +74,13 @@ def render_multiple_pages(app, num: int): rx.select( ["C", "PF", "SF", "PG", "SG"], placeholder="Select a position. (All)", - on_change=State.set_position, # type: ignore + on_change=State.set_position, # pyright: ignore [reportAttributeAccessIssue] size="3", ), rx.select( college, placeholder="Select a college. (All)", - on_change=State.set_college, # type: ignore + on_change=State.set_college, # pyright: ignore [reportAttributeAccessIssue] size="3", ), ), @@ -95,7 +95,7 @@ def render_multiple_pages(app, num: int): default_value=[18, 50], min=18, max=50, - on_value_commit=State.set_age, # type: ignore + on_value_commit=State.set_age, # pyright: ignore [reportAttributeAccessIssue] ), align_items="left", width="100%", @@ -110,7 +110,7 @@ def render_multiple_pages(app, num: int): default_value=[0, 25000000], min=0, max=25000000, - on_value_commit=State.set_salary, # type: ignore + on_value_commit=State.set_salary, # pyright: ignore [reportAttributeAccessIssue] ), align_items="left", width="100%", @@ -130,7 +130,7 @@ def render_multiple_pages(app, num: int): def AppWithOnePage(): """A reflex app with one page.""" - from rxconfig import config # type: ignore + from rxconfig import config # pyright: ignore [reportMissingImports] import reflex as rx @@ -232,7 +232,7 @@ def app_with_ten_pages( root=root, app_source=functools.partial( AppWithTenPages, - render_comp=render_multiple_pages, # type: ignore + render_comp=render_multiple_pages, # pyright: ignore [reportCallIssue] ), ) @@ -255,9 +255,9 @@ def app_with_hundred_pages( root=root, app_source=functools.partial( AppWithHundredPages, - render_comp=render_multiple_pages, # type: ignore + render_comp=render_multiple_pages, # pyright: ignore [reportCallIssue] ), - ) # type: ignore + ) @pytest.fixture(scope="session") @@ -278,9 +278,9 @@ def app_with_thousand_pages( root=root, app_source=functools.partial( AppWithThousandPages, - render_comp=render_multiple_pages, # type: ignore + render_comp=render_multiple_pages, # pyright: ignore [reportCallIssue] ), - ) # type: ignore + ) @pytest.fixture(scope="session") @@ -301,9 +301,9 @@ def app_with_ten_thousand_pages( root=root, app_source=functools.partial( AppWithTenThousandPages, - render_comp=render_multiple_pages, # type: ignore + render_comp=render_multiple_pages, # pyright: ignore [reportCallIssue] ), - ) # type: ignore + ) @pytest.mark.skipif(constants.IS_WINDOWS, reason=WINDOWS_SKIP_REASON) diff --git a/poetry.lock b/poetry.lock index 68e8e37db..f8d4cf949 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. [[package]] name = "alembic" @@ -86,15 +86,15 @@ files = [ [[package]] name = "attrs" -version = "24.3.0" +version = "25.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.8" groups = ["dev"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"}, - {file = "attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff"}, + {file = "attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"}, + {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"}, ] [package.extras] @@ -620,25 +620,25 @@ test = ["pytest (>=6)"] [[package]] name = "fastapi" -version = "0.115.6" +version = "0.115.7" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" groups = ["main"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "fastapi-0.115.6-py3-none-any.whl", hash = "sha256:e9240b29e36fa8f4bb7290316988e90c381e5092e0cbe84e7818cc3713bcf305"}, - {file = "fastapi-0.115.6.tar.gz", hash = "sha256:9ec46f7addc14ea472958a96aae5b5de65f39721a46aaf5705c480d9a8b76654"}, + {file = "fastapi-0.115.7-py3-none-any.whl", hash = "sha256:eb6a8c8bf7f26009e8147111ff15b5177a0e19bb4a45bc3486ab14804539d21e"}, + {file = "fastapi-0.115.7.tar.gz", hash = "sha256:0f106da6c01d88a6786b3248fb4d7a940d071f6f488488898ad5d354b25ed015"}, ] [package.dependencies] pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.40.0,<0.42.0" +starlette = ">=0.40.0,<0.46.0" typing-extensions = ">=4.8.0" [package.extras] -all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] -standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] +all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "filelock" @@ -740,7 +740,7 @@ files = [ {file = "greenlet-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22"}, {file = "greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467"}, ] -markers = {main = "python_version < \"3.14\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\") and (python_version <= \"3.11\" or python_version >= \"3.12\")", dev = "python_version <= \"3.11\" or python_version >= \"3.12\""} +markers = {main = "(python_version <= \"3.11\" or python_version >= \"3.12\") and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\") and python_version < \"3.14\"", dev = "python_version <= \"3.11\" or python_version >= \"3.12\""} [package.extras] docs = ["Sphinx", "furo"] @@ -1540,39 +1540,6 @@ tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "ole typing = ["typing-extensions"] xmp = ["defusedxml"] -[[package]] -name = "pip" -version = "24.3.1" -description = "The PyPA recommended tool for installing Python packages." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pip-24.3.1-py3-none-any.whl", hash = "sha256:3790624780082365f47549d032f3770eeb2b1e8bd1f7b2e02dace1afa361b4ed"}, - {file = "pip-24.3.1.tar.gz", hash = "sha256:ebcb60557f2aefabc2e0f918751cd24ea0d56d8ec5445fe1807f1d2109660b99"}, -] - -[[package]] -name = "pipdeptree" -version = "2.16.2" -description = "Command line utility to show dependency tree of packages." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "pipdeptree-2.16.2-py3-none-any.whl", hash = "sha256:4b60a20f632aa3449880141d1cd0bc99cb5f93ed46d54d689fd1c9b95f0e53d0"}, - {file = "pipdeptree-2.16.2.tar.gz", hash = "sha256:96ecde8e6f40c95998491a385e4af56d387f94ff7d3b8f209aa34982a721bc43"}, -] - -[package.dependencies] -pip = ">=23.1.2" - -[package.extras] -graphviz = ["graphviz (>=0.20.1)"] -test = ["covdefaults (>=2.3)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "virtualenv (>=20.25,<21)"] - [[package]] name = "platformdirs" version = "4.3.6" @@ -1727,15 +1694,15 @@ markers = {main = "(platform_machine != \"ppc64le\" and platform_machine != \"s3 [[package]] name = "pydantic" -version = "2.10.5" +version = "2.10.6" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" groups = ["main"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"}, - {file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"}, + {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, + {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, ] [package.dependencies] @@ -1911,23 +1878,25 @@ files = [ [[package]] name = "pyright" -version = "1.1.334" +version = "1.1.392.post0" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" groups = ["dev"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "pyright-1.1.334-py3-none-any.whl", hash = "sha256:dcb13e8358e021189672c4d6ebcad192ab061e4c7225036973ec493183c6da68"}, - {file = "pyright-1.1.334.tar.gz", hash = "sha256:3adaf10f1f4209575dc022f9c897f7ef024639b7ea5b3cbe49302147e6949cd4"}, + {file = "pyright-1.1.392.post0-py3-none-any.whl", hash = "sha256:252f84458a46fa2f0fd4e2f91fc74f50b9ca52c757062e93f6c250c0d8329eb2"}, + {file = "pyright-1.1.392.post0.tar.gz", hash = "sha256:3b7f88de74a28dcfa90c7d90c782b6569a48c2be5f9d4add38472bdaac247ebd"}, ] [package.dependencies] nodeenv = ">=1.6.0" +typing-extensions = ">=4.1" [package.extras] -all = ["twine (>=3.4.1)"] +all = ["nodejs-wheel-binaries", "twine (>=3.4.1)"] dev = ["twine (>=3.4.1)"] +nodejs = ["nodejs-wheel-binaries"] [[package]] name = "pysocks" @@ -1969,15 +1938,15 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments [[package]] name = "pytest-asyncio" -version = "0.25.2" +version = "0.25.3" description = "Pytest support for asyncio" optional = false python-versions = ">=3.9" groups = ["dev"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "pytest_asyncio-0.25.2-py3-none-any.whl", hash = "sha256:0d0bb693f7b99da304a0634afc0a4b19e49d5e0de2d670f38dc4bfa5727c5075"}, - {file = "pytest_asyncio-0.25.2.tar.gz", hash = "sha256:3f8ef9a98f45948ea91a0ed3dc4268b5326c0e7bce73892acc654df4262ad45f"}, + {file = "pytest_asyncio-0.25.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3"}, + {file = "pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a"}, ] [package.dependencies] @@ -2093,7 +2062,7 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main", "dev"] +groups = ["dev"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, @@ -2311,29 +2280,26 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==23.2.1)", "requests (>=2.31.0)" [[package]] name = "reflex-hosting-cli" -version = "0.1.32" +version = "0.1.33" description = "Reflex Hosting CLI" optional = false -python-versions = "<4.0,>=3.8" +python-versions = "<4.0,>=3.9" groups = ["main"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "reflex_hosting_cli-0.1.32-py3-none-any.whl", hash = "sha256:86b4222f3e99d949a209be7de8c457ededebc1f12a721ee6669c6c35fdecc508"}, - {file = "reflex_hosting_cli-0.1.32.tar.gz", hash = "sha256:0b8e4b4b30d9261bf6d720265f1c428b2840bb630896e60a1a2faa095901ed59"}, + {file = "reflex_hosting_cli-0.1.33-py3-none-any.whl", hash = "sha256:3fe72fc448a231c61de4ac646f42c936c70e91330f616a23aec658f905d53bc4"}, + {file = "reflex_hosting_cli-0.1.33.tar.gz", hash = "sha256:81c4a896b106eea99f1cab53ea23a6e19802592ce0468cc38d93d440bc95263a"}, ] [package.dependencies] charset-normalizer = ">=3.3.2,<4.0.0" httpx = ">=0.25.1,<1.0" -pipdeptree = ">=2.13.1,<2.17.0" platformdirs = ">=3.10.0,<5.0" pydantic = ">=1.10.2,<3.0" -python-dateutil = ">=2.8.1" pyyaml = ">=6.0.2,<7.0.0" rich = ">=13.0.0,<14.0" tabulate = ">=0.9.0,<0.10.0" typer = ">=0.15.0,<1" -websockets = ">=10.4" [[package]] name = "requests" @@ -2459,15 +2425,15 @@ jeepney = ">=0.6" [[package]] name = "selenium" -version = "4.28.0" +version = "4.28.1" description = "Official Python bindings for Selenium WebDriver" optional = false python-versions = ">=3.9" groups = ["dev"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "selenium-4.28.0-py3-none-any.whl", hash = "sha256:3d6a2e8e1b850a1078884ea19f4e011ecdc12263434d87a0b78769836fb82dd8"}, - {file = "selenium-4.28.0.tar.gz", hash = "sha256:a9fae6eef48d470a1b0c6e45185d96f0dafb025e8da4b346cc41e4da3ac54fa0"}, + {file = "selenium-4.28.1-py3-none-any.whl", hash = "sha256:4238847e45e24e4472cfcf3554427512c7aab9443396435b1623ef406fff1cc1"}, + {file = "selenium-4.28.1.tar.gz", hash = "sha256:0072d08670d7ec32db901bd0107695a330cecac9f196e3afb3fa8163026e022a"}, ] [package.dependencies] @@ -2539,7 +2505,7 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main", "dev"] +groups = ["dev"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, @@ -2688,22 +2654,22 @@ SQLAlchemy = ">=2.0.14,<2.1.0" [[package]] name = "starlette" -version = "0.41.3" +version = "0.45.3" description = "The little ASGI library that shines." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "starlette-0.41.3-py3-none-any.whl", hash = "sha256:44cedb2b7c77a9de33a8b74b2b90e9f50d11fcf25d8270ea525ad71a25374ff7"}, - {file = "starlette-0.41.3.tar.gz", hash = "sha256:0e4ab3d16522a255be6b28260b938eae2482f98ce5cc934cb08dce8dc3ba5835"}, + {file = "starlette-0.45.3-py3-none-any.whl", hash = "sha256:dfb6d332576f136ec740296c7e8bb8c8a7125044e7c6da30744718880cdd059d"}, + {file = "starlette-0.45.3.tar.gz", hash = "sha256:2cbcba2a75806f8a41c722141486f37c28e30a0921c5f6fe4346cb0dcee1302f"}, ] [package.dependencies] -anyio = ">=3.4.0,<5" +anyio = ">=3.6.2,<5" [package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] +full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"] [[package]] name = "starlette-admin" @@ -3040,86 +3006,6 @@ docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] optional = ["python-socks", "wsaccel"] test = ["websockets"] -[[package]] -name = "websockets" -version = "14.2" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" -files = [ - {file = "websockets-14.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e8179f95323b9ab1c11723e5d91a89403903f7b001828161b480a7810b334885"}, - {file = "websockets-14.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0d8c3e2cdb38f31d8bd7d9d28908005f6fa9def3324edb9bf336d7e4266fd397"}, - {file = "websockets-14.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:714a9b682deb4339d39ffa674f7b674230227d981a37d5d174a4a83e3978a610"}, - {file = "websockets-14.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2e53c72052f2596fb792a7acd9704cbc549bf70fcde8a99e899311455974ca3"}, - {file = "websockets-14.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e3fbd68850c837e57373d95c8fe352203a512b6e49eaae4c2f4088ef8cf21980"}, - {file = "websockets-14.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b27ece32f63150c268593d5fdb82819584831a83a3f5809b7521df0685cd5d8"}, - {file = "websockets-14.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4daa0faea5424d8713142b33825fff03c736f781690d90652d2c8b053345b0e7"}, - {file = "websockets-14.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:bc63cee8596a6ec84d9753fd0fcfa0452ee12f317afe4beae6b157f0070c6c7f"}, - {file = "websockets-14.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a570862c325af2111343cc9b0257b7119b904823c675b22d4ac547163088d0d"}, - {file = "websockets-14.2-cp310-cp310-win32.whl", hash = "sha256:75862126b3d2d505e895893e3deac0a9339ce750bd27b4ba515f008b5acf832d"}, - {file = "websockets-14.2-cp310-cp310-win_amd64.whl", hash = "sha256:cc45afb9c9b2dc0852d5c8b5321759cf825f82a31bfaf506b65bf4668c96f8b2"}, - {file = "websockets-14.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3bdc8c692c866ce5fefcaf07d2b55c91d6922ac397e031ef9b774e5b9ea42166"}, - {file = "websockets-14.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c93215fac5dadc63e51bcc6dceca72e72267c11def401d6668622b47675b097f"}, - {file = "websockets-14.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1c9b6535c0e2cf8a6bf938064fb754aaceb1e6a4a51a80d884cd5db569886910"}, - {file = "websockets-14.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a52a6d7cf6938e04e9dceb949d35fbdf58ac14deea26e685ab6368e73744e4c"}, - {file = "websockets-14.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f05702e93203a6ff5226e21d9b40c037761b2cfb637187c9802c10f58e40473"}, - {file = "websockets-14.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22441c81a6748a53bfcb98951d58d1af0661ab47a536af08920d129b4d1c3473"}, - {file = "websockets-14.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd9b868d78b194790e6236d9cbc46d68aba4b75b22497eb4ab64fa640c3af56"}, - {file = "websockets-14.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1a5a20d5843886d34ff8c57424cc65a1deda4375729cbca4cb6b3353f3ce4142"}, - {file = "websockets-14.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:34277a29f5303d54ec6468fb525d99c99938607bc96b8d72d675dee2b9f5bf1d"}, - {file = "websockets-14.2-cp311-cp311-win32.whl", hash = "sha256:02687db35dbc7d25fd541a602b5f8e451a238ffa033030b172ff86a93cb5dc2a"}, - {file = "websockets-14.2-cp311-cp311-win_amd64.whl", hash = "sha256:862e9967b46c07d4dcd2532e9e8e3c2825e004ffbf91a5ef9dde519ee2effb0b"}, - {file = "websockets-14.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1f20522e624d7ffbdbe259c6b6a65d73c895045f76a93719aa10cd93b3de100c"}, - {file = "websockets-14.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:647b573f7d3ada919fd60e64d533409a79dcf1ea21daeb4542d1d996519ca967"}, - {file = "websockets-14.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6af99a38e49f66be5a64b1e890208ad026cda49355661549c507152113049990"}, - {file = "websockets-14.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:091ab63dfc8cea748cc22c1db2814eadb77ccbf82829bac6b2fbe3401d548eda"}, - {file = "websockets-14.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b374e8953ad477d17e4851cdc66d83fdc2db88d9e73abf755c94510ebddceb95"}, - {file = "websockets-14.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a39d7eceeea35db85b85e1169011bb4321c32e673920ae9c1b6e0978590012a3"}, - {file = "websockets-14.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0a6f3efd47ffd0d12080594f434faf1cd2549b31e54870b8470b28cc1d3817d9"}, - {file = "websockets-14.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:065ce275e7c4ffb42cb738dd6b20726ac26ac9ad0a2a48e33ca632351a737267"}, - {file = "websockets-14.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e9d0e53530ba7b8b5e389c02282f9d2aa47581514bd6049d3a7cffe1385cf5fe"}, - {file = "websockets-14.2-cp312-cp312-win32.whl", hash = "sha256:20e6dd0984d7ca3037afcb4494e48c74ffb51e8013cac71cf607fffe11df7205"}, - {file = "websockets-14.2-cp312-cp312-win_amd64.whl", hash = "sha256:44bba1a956c2c9d268bdcdf234d5e5ff4c9b6dc3e300545cbe99af59dda9dcce"}, - {file = "websockets-14.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6f1372e511c7409a542291bce92d6c83320e02c9cf392223272287ce55bc224e"}, - {file = "websockets-14.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4da98b72009836179bb596a92297b1a61bb5a830c0e483a7d0766d45070a08ad"}, - {file = "websockets-14.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8a86a269759026d2bde227652b87be79f8a734e582debf64c9d302faa1e9f03"}, - {file = "websockets-14.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86cf1aaeca909bf6815ea714d5c5736c8d6dd3a13770e885aafe062ecbd04f1f"}, - {file = "websockets-14.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9b0f6c3ba3b1240f602ebb3971d45b02cc12bd1845466dd783496b3b05783a5"}, - {file = "websockets-14.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:669c3e101c246aa85bc8534e495952e2ca208bd87994650b90a23d745902db9a"}, - {file = "websockets-14.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eabdb28b972f3729348e632ab08f2a7b616c7e53d5414c12108c29972e655b20"}, - {file = "websockets-14.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2066dc4cbcc19f32c12a5a0e8cc1b7ac734e5b64ac0a325ff8353451c4b15ef2"}, - {file = "websockets-14.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ab95d357cd471df61873dadf66dd05dd4709cae001dd6342edafc8dc6382f307"}, - {file = "websockets-14.2-cp313-cp313-win32.whl", hash = "sha256:a9e72fb63e5f3feacdcf5b4ff53199ec8c18d66e325c34ee4c551ca748623bbc"}, - {file = "websockets-14.2-cp313-cp313-win_amd64.whl", hash = "sha256:b439ea828c4ba99bb3176dc8d9b933392a2413c0f6b149fdcba48393f573377f"}, - {file = "websockets-14.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7cd5706caec1686c5d233bc76243ff64b1c0dc445339bd538f30547e787c11fe"}, - {file = "websockets-14.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ec607328ce95a2f12b595f7ae4c5d71bf502212bddcea528290b35c286932b12"}, - {file = "websockets-14.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da85651270c6bfb630136423037dd4975199e5d4114cae6d3066641adcc9d1c7"}, - {file = "websockets-14.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3ecadc7ce90accf39903815697917643f5b7cfb73c96702318a096c00aa71f5"}, - {file = "websockets-14.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1979bee04af6a78608024bad6dfcc0cc930ce819f9e10342a29a05b5320355d0"}, - {file = "websockets-14.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dddacad58e2614a24938a50b85969d56f88e620e3f897b7d80ac0d8a5800258"}, - {file = "websockets-14.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:89a71173caaf75fa71a09a5f614f450ba3ec84ad9fca47cb2422a860676716f0"}, - {file = "websockets-14.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6af6a4b26eea4fc06c6818a6b962a952441e0e39548b44773502761ded8cc1d4"}, - {file = "websockets-14.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:80c8efa38957f20bba0117b48737993643204645e9ec45512579132508477cfc"}, - {file = "websockets-14.2-cp39-cp39-win32.whl", hash = "sha256:2e20c5f517e2163d76e2729104abc42639c41cf91f7b1839295be43302713661"}, - {file = "websockets-14.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4c8cef610e8d7c70dea92e62b6814a8cd24fbd01d7103cc89308d2bfe1659ef"}, - {file = "websockets-14.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d7d9cafbccba46e768be8a8ad4635fa3eae1ffac4c6e7cb4eb276ba41297ed29"}, - {file = "websockets-14.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c76193c1c044bd1e9b3316dcc34b174bbf9664598791e6fb606d8d29000e070c"}, - {file = "websockets-14.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd475a974d5352390baf865309fe37dec6831aafc3014ffac1eea99e84e83fc2"}, - {file = "websockets-14.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c6c0097a41968b2e2b54ed3424739aab0b762ca92af2379f152c1aef0187e1c"}, - {file = "websockets-14.2-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d7ff794c8b36bc402f2e07c0b2ceb4a2424147ed4785ff03e2a7af03711d60a"}, - {file = "websockets-14.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dec254fcabc7bd488dab64846f588fc5b6fe0d78f641180030f8ea27b76d72c3"}, - {file = "websockets-14.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:bbe03eb853e17fd5b15448328b4ec7fb2407d45fb0245036d06a3af251f8e48f"}, - {file = "websockets-14.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a3c4aa3428b904d5404a0ed85f3644d37e2cb25996b7f096d77caeb0e96a3b42"}, - {file = "websockets-14.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:577a4cebf1ceaf0b65ffc42c54856214165fb8ceeba3935852fc33f6b0c55e7f"}, - {file = "websockets-14.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad1c1d02357b7665e700eca43a31d52814ad9ad9b89b58118bdabc365454b574"}, - {file = "websockets-14.2-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f390024a47d904613577df83ba700bd189eedc09c57af0a904e5c39624621270"}, - {file = "websockets-14.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3c1426c021c38cf92b453cdf371228d3430acd775edee6bac5a4d577efc72365"}, - {file = "websockets-14.2-py3-none-any.whl", hash = "sha256:7a6ceec4ea84469f15cf15807a747e9efe57e369c384fa86e022b3bea679b79b"}, - {file = "websockets-14.2.tar.gz", hash = "sha256:5059ed9c54945efb321f097084b4c7e52c246f2c869815876a69d1efc4ad6eb5"}, -] - [[package]] name = "wheel" version = "0.45.1" @@ -3266,4 +3152,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.10, <4.0" -content-hash = "376707066a00c43aef555c6db2ccb0ddfde0ee9011e8f20110d728fb723f1662" +content-hash = "35c503a68e87896b4f7d7c209dd3fe6d707ebcc1702377cab0a1339554c6ad77" diff --git a/pyproject.toml b/pyproject.toml index d19d1a0ac..761f9e2c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,7 @@ typing_extensions = ">=4.6.0" [tool.poetry.group.dev.dependencies] pytest = ">=7.1.2,<9.0" pytest-mock = ">=3.10.0,<4.0" -pyright = ">=1.1.229,<1.1.335" +pyright = ">=1.1.392, <1.2" darglint = ">=1.8.1,<2.0" dill = ">=0.3.8" toml = ">=0.10.2,<1.0" @@ -80,12 +80,13 @@ requires = ["poetry-core>=1.5.1"] build-backend = "poetry.core.masonry.api" [tool.pyright] +reportIncompatibleMethodOverride = false [tool.ruff] target-version = "py310" output-format = "concise" lint.isort.split-on-trailing-comma = false -lint.select = ["B", "C4", "D", "E", "ERA", "F", "FURB", "I", "N", "PERF", "PTH", "RUF", "SIM", "T", "TRY", "W"] +lint.select = ["B", "C4", "D", "E", "ERA", "F", "FURB", "I", "N", "PERF", "PGH", "PTH", "RUF", "SIM", "T", "TRY", "W"] lint.ignore = ["B008", "D205", "E501", "F403", "SIM115", "RUF006", "RUF012", "TRY0"] lint.pydocstyle.convention = "google" @@ -94,7 +95,7 @@ lint.pydocstyle.convention = "google" "tests/*.py" = ["D100", "D103", "D104", "B018", "PERF", "T", "N"] "benchmarks/*.py" = ["D100", "D103", "D104", "B018", "PERF", "T", "N"] "reflex/.templates/*.py" = ["D100", "D103", "D104"] -"*.pyi" = ["D301", "D415", "D417", "D418", "E742", "N"] +"*.pyi" = ["D301", "D415", "D417", "D418", "E742", "N", "PGH"] "pyi_generator.py" = ["N802"] "reflex/constants/*.py" = ["N"] "*/blank.py" = ["I001"] diff --git a/reflex/__init__.pyi b/reflex/__init__.pyi index 1f9b4ecd8..5c80269ad 100644 --- a/reflex/__init__.pyi +++ b/reflex/__init__.pyi @@ -131,7 +131,7 @@ from .components.radix.themes.layout.container import container as container from .components.radix.themes.layout.flex import flex as flex from .components.radix.themes.layout.grid import grid as grid from .components.radix.themes.layout.list import list_item as list_item -from .components.radix.themes.layout.list import list_ns as list # noqa +from .components.radix.themes.layout.list import list_ns as list # noqa: F401 from .components.radix.themes.layout.list import ordered_list as ordered_list from .components.radix.themes.layout.list import unordered_list as unordered_list from .components.radix.themes.layout.section import section as section diff --git a/reflex/app.py b/reflex/app.py index 20c01cba6..e3b45e7b2 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -146,7 +146,7 @@ def default_backend_exception_handler(exception: Exception) -> EventSpec: position="top-center", id="backend_error", style={"width": "500px"}, - ) # type: ignore + ) # pyright: ignore [reportReturnType] else: error_message.insert(0, "An error occurred.") return window_alert("\n".join(error_message)) @@ -780,7 +780,7 @@ class App(MiddlewareMixin, LifespanMixin): frontend_packages = get_config().frontend_packages _frontend_packages = [] for package in frontend_packages: - if package in (get_config().tailwind or {}).get("plugins", []): # type: ignore + if package in (get_config().tailwind or {}).get("plugins", []): console.warn( f"Tailwind packages are inferred from 'plugins', remove `{package}` from `frontend_packages`" ) @@ -1025,7 +1025,7 @@ class App(MiddlewareMixin, LifespanMixin): compiler.compile_document_root( self.head_components, html_lang=self.html_lang, - html_custom_attrs=self.html_custom_attrs, # type: ignore + html_custom_attrs=self.html_custom_attrs, # pyright: ignore [reportArgumentType] ) ) diff --git a/reflex/app_mixins/lifespan.py b/reflex/app_mixins/lifespan.py index 9403e0f35..8bdef2eb9 100644 --- a/reflex/app_mixins/lifespan.py +++ b/reflex/app_mixins/lifespan.py @@ -32,7 +32,7 @@ class LifespanMixin(AppMixin): try: async with contextlib.AsyncExitStack() as stack: for task in self.lifespan_tasks: - run_msg = f"Started lifespan task: {task.__name__} as {{type}}" # type: ignore + run_msg = f"Started lifespan task: {task.__name__} as {{type}}" # pyright: ignore [reportAttributeAccessIssue] if isinstance(task, asyncio.Task): running_tasks.append(task) else: @@ -73,7 +73,7 @@ class LifespanMixin(AppMixin): if task_kwargs: original_task = task - task = functools.partial(task, **task_kwargs) # type: ignore - functools.update_wrapper(task, original_task) # type: ignore - self.lifespan_tasks.add(task) # type: ignore - console.debug(f"Registered lifespan task: {task.__name__}") # type: ignore + task = functools.partial(task, **task_kwargs) # pyright: ignore [reportArgumentType] + functools.update_wrapper(task, original_task) # pyright: ignore [reportArgumentType] + self.lifespan_tasks.add(task) + console.debug(f"Registered lifespan task: {task.__name__}") # pyright: ignore [reportAttributeAccessIssue] diff --git a/reflex/app_mixins/middleware.py b/reflex/app_mixins/middleware.py index 30593d9ae..c81fd7806 100644 --- a/reflex/app_mixins/middleware.py +++ b/reflex/app_mixins/middleware.py @@ -53,11 +53,11 @@ class MiddlewareMixin(AppMixin): """ for middleware in self.middleware: if asyncio.iscoroutinefunction(middleware.preprocess): - out = await middleware.preprocess(app=self, state=state, event=event) # type: ignore + out = await middleware.preprocess(app=self, state=state, event=event) # pyright: ignore [reportArgumentType] else: - out = middleware.preprocess(app=self, state=state, event=event) # type: ignore + out = middleware.preprocess(app=self, state=state, event=event) # pyright: ignore [reportArgumentType] if out is not None: - return out # type: ignore + return out # pyright: ignore [reportReturnType] async def _postprocess( self, state: BaseState, event: Event, update: StateUpdate @@ -78,18 +78,18 @@ class MiddlewareMixin(AppMixin): for middleware in self.middleware: if asyncio.iscoroutinefunction(middleware.postprocess): out = await middleware.postprocess( - app=self, # type: ignore + app=self, # pyright: ignore [reportArgumentType] state=state, event=event, update=update, ) else: out = middleware.postprocess( - app=self, # type: ignore + app=self, # pyright: ignore [reportArgumentType] state=state, event=event, update=update, ) if out is not None: - return out # type: ignore + return out # pyright: ignore [reportReturnType] return update diff --git a/reflex/base.py b/reflex/base.py index a88e557ef..5c0180812 100644 --- a/reflex/base.py +++ b/reflex/base.py @@ -13,7 +13,7 @@ except ModuleNotFoundError: if not TYPE_CHECKING: import pydantic.main as pydantic_main from pydantic import BaseModel - from pydantic.fields import ModelField # type: ignore + from pydantic.fields import ModelField def validate_field_name(bases: List[Type["BaseModel"]], field_name: str) -> None: @@ -44,13 +44,13 @@ def validate_field_name(bases: List[Type["BaseModel"]], field_name: str) -> None # monkeypatch pydantic validate_field_name method to skip validating # shadowed state vars when reloading app via utils.prerequisites.get_app(reload=True) -pydantic_main.validate_field_name = validate_field_name # type: ignore +pydantic_main.validate_field_name = validate_field_name # pyright: ignore [reportPossiblyUnboundVariable, reportPrivateImportUsage] if TYPE_CHECKING: from reflex.vars import Var -class Base(BaseModel): # pyright: ignore [reportUnboundVariable] +class Base(BaseModel): # pyright: ignore [reportPossiblyUnboundVariable] """The base class subclassed by all Reflex classes. This class wraps Pydantic and provides common methods such as @@ -75,7 +75,7 @@ class Base(BaseModel): # pyright: ignore [reportUnboundVariable] """ from reflex.utils.serializers import serialize - return self.__config__.json_dumps( # type: ignore + return self.__config__.json_dumps( self.dict(), default=serialize, ) @@ -113,12 +113,12 @@ class Base(BaseModel): # pyright: ignore [reportUnboundVariable] default_value: The default value of the field """ var_name = var._var_field_name - new_field = ModelField.infer( + new_field = ModelField.infer( # pyright: ignore [reportPossiblyUnboundVariable] name=var_name, value=default_value, annotation=var._var_type, class_validators=None, - config=cls.__config__, # type: ignore + config=cls.__config__, ) cls.__fields__.update({var_name: new_field}) diff --git a/reflex/compiler/utils.py b/reflex/compiler/utils.py index c0ba28f4b..02692e43b 100644 --- a/reflex/compiler/utils.py +++ b/reflex/compiler/utils.py @@ -12,7 +12,9 @@ from reflex.vars.base import Var try: from pydantic.v1.fields import ModelField except ModuleNotFoundError: - from pydantic.fields import ModelField # type: ignore + from pydantic.fields import ( + ModelField, # pyright: ignore [reportAttributeAccessIssue] + ) from reflex import constants from reflex.components.base import ( @@ -115,7 +117,7 @@ def compile_imports(import_dict: ParsedImportDict) -> list[dict]: default, rest = compile_import_statement(fields) # prevent lib from being rendered on the page if all imports are non rendered kind - if not any(f.render for f in fields): # type: ignore + if not any(f.render for f in fields): continue if not lib: diff --git a/reflex/components/base/bare.py b/reflex/components/base/bare.py index e576fac85..0f0bef8b9 100644 --- a/reflex/components/base/bare.py +++ b/reflex/components/base/bare.py @@ -31,7 +31,7 @@ class Bare(Component): return cls(contents=contents) else: contents = str(contents) if contents is not None else "" - return cls(contents=contents) # type: ignore + return cls(contents=contents) def _get_all_hooks_internal(self) -> dict[str, VarData | None]: """Include the hooks for the component. diff --git a/reflex/components/base/meta.py b/reflex/components/base/meta.py index 526233c8b..10264009e 100644 --- a/reflex/components/base/meta.py +++ b/reflex/components/base/meta.py @@ -53,11 +53,11 @@ class Description(Meta): """A component that displays the title of the current page.""" # The type of the description. - name: str = "description" + name: str | None = "description" class Image(Meta): """A component that displays the title of the current page.""" # The type of the image. - property: str = "og:image" + property: str | None = "og:image" diff --git a/reflex/components/component.py b/reflex/components/component.py index 58bdfe7c2..c88330918 100644 --- a/reflex/components/component.py +++ b/reflex/components/component.py @@ -150,7 +150,7 @@ class BaseComponent(Base, ABC): class ComponentNamespace(SimpleNamespace): """A namespace to manage components with subcomponents.""" - def __hash__(self) -> int: + def __hash__(self) -> int: # pyright: ignore [reportIncompatibleVariableOverride] """Get the hash of the namespace. Returns: @@ -462,9 +462,7 @@ class Component(BaseComponent, ABC): if types.is_union(passed_type): # We need to check all possible types in the union. passed_types = ( - arg - for arg in passed_type.__args__ # type: ignore - if arg is not type(None) + arg for arg in passed_type.__args__ if arg is not type(None) ) if ( # If the passed var is a union, check if all possible types are valid. @@ -491,7 +489,7 @@ class Component(BaseComponent, ABC): # Check if the key is an event trigger. if key in component_specific_triggers: kwargs["event_triggers"][key] = EventChain.create( - value=value, # type: ignore + value=value, args_spec=component_specific_triggers[key], key=key, ) @@ -578,7 +576,7 @@ class Component(BaseComponent, ABC): annotation = field.annotation if (metadata := getattr(annotation, "__metadata__", None)) is not None: args_spec = metadata[0] - default_triggers[field.name] = args_spec or (no_args_event_spec) # type: ignore + default_triggers[field.name] = args_spec or (no_args_event_spec) return default_triggers def __repr__(self) -> str: @@ -761,7 +759,7 @@ class Component(BaseComponent, ABC): # Walk the MRO to call all `add_style` methods. for base in self._iter_parent_classes_with_method("add_style"): - s = base.add_style(self) # type: ignore + s = base.add_style(self) if s is not None: styles.append(s) @@ -1674,7 +1672,7 @@ class CustomComponent(Component): if base_value is not None and isinstance(value, Component): self.component_props[key] = value value = base_value._replace( - merge_var_data=VarData( # type: ignore + merge_var_data=VarData( imports=value._get_all_imports(), hooks=value._get_all_hooks(), ) @@ -1707,7 +1705,7 @@ class CustomComponent(Component): return hash(self.tag) @classmethod - def get_props(cls) -> Set[str]: + def get_props(cls) -> Set[str]: # pyright: ignore [reportIncompatibleVariableOverride] """Get the props for the component. Returns: @@ -1802,7 +1800,7 @@ class CustomComponent(Component): include_children=include_children, ignore_ids=ignore_ids ) - @lru_cache(maxsize=None) # noqa + @lru_cache(maxsize=None) # noqa: B019 def get_component(self) -> Component: """Render the component. diff --git a/reflex/components/core/banner.py b/reflex/components/core/banner.py index b7b6fae6c..6479bf3b2 100644 --- a/reflex/components/core/banner.py +++ b/reflex/components/core/banner.py @@ -25,7 +25,7 @@ from reflex.vars.function import FunctionStringVar from reflex.vars.number import BooleanVar from reflex.vars.sequence import LiteralArrayVar -connect_error_var_data: VarData = VarData( # type: ignore +connect_error_var_data: VarData = VarData( imports=Imports.EVENTS, hooks={Hooks.EVENTS: None}, ) @@ -99,14 +99,14 @@ class ConnectionToaster(Toaster): """ toast_id = "websocket-error" target_url = WebsocketTargetURL.create() - props = ToastProps( # type: ignore + props = ToastProps( description=LiteralVar.create( f"Check if server is reachable at {target_url}", ), close_button=True, duration=120000, id=toast_id, - ) + ) # pyright: ignore [reportCallIssue] individual_hooks = [ f"const toast_props = {LiteralVar.create(props)!s};", @@ -116,7 +116,7 @@ class ConnectionToaster(Toaster): _var_data=VarData( imports={ "react": ["useEffect", "useState"], - **dict(target_url._get_all_var_data().imports), # type: ignore + **dict(target_url._get_all_var_data().imports), # pyright: ignore [reportArgumentType, reportOptionalMemberAccess] } ), ).call( diff --git a/reflex/components/core/cond.py b/reflex/components/core/cond.py index 488990f54..25b691808 100644 --- a/reflex/components/core/cond.py +++ b/reflex/components/core/cond.py @@ -26,10 +26,9 @@ class Cond(MemoizationLeaf): cond: Var[Any] # The component to render if the cond is true. - comp1: BaseComponent = None # type: ignore - + comp1: BaseComponent | None = None # The component to render if the cond is false. - comp2: BaseComponent = None # type: ignore + comp2: BaseComponent | None = None @classmethod def create( @@ -73,8 +72,8 @@ class Cond(MemoizationLeaf): def _render(self) -> Tag: return CondTag( cond=self.cond, - true_value=self.comp1.render(), - false_value=self.comp2.render(), + true_value=self.comp1.render(), # pyright: ignore [reportOptionalMemberAccess] + false_value=self.comp2.render(), # pyright: ignore [reportOptionalMemberAccess] ) def render(self) -> Dict: @@ -111,7 +110,7 @@ class Cond(MemoizationLeaf): @overload -def cond(condition: Any, c1: Component, c2: Any) -> Component: ... +def cond(condition: Any, c1: Component, c2: Any) -> Component: ... # pyright: ignore [reportOverlappingOverload] @overload @@ -163,16 +162,16 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | Var: # Create the conditional var. return ternary_operation( - cond_var.bool()._replace( # type: ignore + cond_var.bool()._replace( merge_var_data=VarData(imports=_IS_TRUE_IMPORT), - ), # type: ignore + ), c1, c2, ) @overload -def color_mode_cond(light: Component, dark: Component | None = None) -> Component: ... # type: ignore +def color_mode_cond(light: Component, dark: Component | None = None) -> Component: ... # pyright: ignore [reportOverlappingOverload] @overload diff --git a/reflex/components/core/debounce.py b/reflex/components/core/debounce.py index 12cc94426..1d798994d 100644 --- a/reflex/components/core/debounce.py +++ b/reflex/components/core/debounce.py @@ -28,7 +28,7 @@ class DebounceInput(Component): min_length: Var[int] # Time to wait between end of input and triggering on_change - debounce_timeout: Var[int] = DEFAULT_DEBOUNCE_TIMEOUT # type: ignore + debounce_timeout: Var[int] = Var.create(DEFAULT_DEBOUNCE_TIMEOUT) # If true, notify when Enter key is pressed force_notify_by_enter: Var[bool] diff --git a/reflex/components/core/match.py b/reflex/components/core/match.py index 8b9382c89..ae8568ac5 100644 --- a/reflex/components/core/match.py +++ b/reflex/components/core/match.py @@ -222,7 +222,7 @@ class Match(MemoizationLeaf): cond=match_cond_var, match_cases=match_cases, default=default, - children=[case[-1] for case in match_cases] + [default], # type: ignore + children=[case[-1] for case in match_cases] + [default], # pyright: ignore [reportArgumentType] ) ) @@ -236,13 +236,13 @@ class Match(MemoizationLeaf): _js_expr=format.format_match( cond=str(match_cond_var), match_cases=match_cases, - default=default, # type: ignore + default=default, # pyright: ignore [reportArgumentType] ), - _var_type=default._var_type, # type: ignore + _var_type=default._var_type, # pyright: ignore [reportAttributeAccessIssue,reportOptionalMemberAccess] _var_data=VarData.merge( match_cond_var._get_all_var_data(), *[el._get_all_var_data() for case in match_cases for el in case], - default._get_all_var_data(), # type: ignore + default._get_all_var_data(), # pyright: ignore [reportAttributeAccessIssue, reportOptionalMemberAccess] ), ) diff --git a/reflex/components/core/upload.py b/reflex/components/core/upload.py index 4666a8f1b..897b89608 100644 --- a/reflex/components/core/upload.py +++ b/reflex/components/core/upload.py @@ -269,7 +269,7 @@ class Upload(MemoizationLeaf): on_drop = upload_props["on_drop"] if isinstance(on_drop, Callable): # Call the lambda to get the event chain. - on_drop = call_event_fn(on_drop, _on_drop_spec) # type: ignore + on_drop = call_event_fn(on_drop, _on_drop_spec) if isinstance(on_drop, EventSpec): # Update the provided args for direct use with on_drop. on_drop = on_drop.with_args( diff --git a/reflex/components/datadisplay/code.py b/reflex/components/datadisplay/code.py index 242e812b2..4f1eb493e 100644 --- a/reflex/components/datadisplay/code.py +++ b/reflex/components/datadisplay/code.py @@ -449,7 +449,7 @@ class CodeBlock(Component, MarkdownComponentMap): if can_copy: code = children[0] - copy_button = ( # type: ignore + copy_button = ( copy_button if copy_button is not None else Button.create( diff --git a/reflex/components/datadisplay/dataeditor.py b/reflex/components/datadisplay/dataeditor.py index f71f97713..b2d6417bd 100644 --- a/reflex/components/datadisplay/dataeditor.py +++ b/reflex/components/datadisplay/dataeditor.py @@ -165,7 +165,7 @@ class DataEditor(NoSSRComponent): tag = "DataEditor" is_default = True - library: str = "@glideapps/glide-data-grid@^6.0.3" + library: str | None = "@glideapps/glide-data-grid@^6.0.3" lib_dependencies: List[str] = [ "lodash@^4.17.21", "react-responsive-carousel@^3.2.7", @@ -321,6 +321,8 @@ class DataEditor(NoSSRComponent): Returns: The import dict. """ + if self.library is None: + return {} return { "": f"{format.format_library_name(self.library)}/dist/index.css", self.library: "GridCellKind", @@ -343,7 +345,7 @@ class DataEditor(NoSSRComponent): data_callback = self.get_cell_content._js_expr else: data_callback = f"getData_{editor_id}" - self.get_cell_content = Var(_js_expr=data_callback) # type: ignore + self.get_cell_content = Var(_js_expr=data_callback) code = [f"function {data_callback}([col, row])" "{"] diff --git a/reflex/components/datadisplay/shiki_code_block.py b/reflex/components/datadisplay/shiki_code_block.py index 3b6bce8a1..2d3040966 100644 --- a/reflex/components/datadisplay/shiki_code_block.py +++ b/reflex/components/datadisplay/shiki_code_block.py @@ -602,7 +602,7 @@ class ShikiCodeBlock(Component, MarkdownComponentMap): transformer_styles = {} # Collect styles from transformers and wrapper - for transformer in code_block.transformers._var_value: # type: ignore + for transformer in code_block.transformers._var_value: # pyright: ignore [reportAttributeAccessIssue] if isinstance(transformer, ShikiBaseTransformers) and transformer.style: transformer_styles.update(transformer.style) transformer_styles.update(code_wrapper_props.pop("style", {})) @@ -653,8 +653,9 @@ class ShikiCodeBlock(Component, MarkdownComponentMap): raise ValueError( f"the function names should be str names of functions in the specified transformer: {library!r}" ) - return ShikiBaseTransformers( # type: ignore - library=library, fns=[FunctionStringVar.create(fn) for fn in fns] + return ShikiBaseTransformers( + library=library, + fns=[FunctionStringVar.create(fn) for fn in fns], # pyright: ignore [reportCallIssue] ) def _render(self, props: dict[str, Any] | None = None): @@ -757,13 +758,13 @@ class ShikiHighLevelCodeBlock(ShikiCodeBlock): if can_copy: code = children[0] - copy_button = ( # type: ignore + copy_button = ( copy_button if copy_button is not None else Button.create( Icon.create(tag="copy", size=16, color=color("gray", 11)), on_click=[ - set_clipboard(cls._strip_transformer_triggers(code)), # type: ignore + set_clipboard(cls._strip_transformer_triggers(code)), copy_script(), ], style=Style( diff --git a/reflex/components/el/constants/reflex.py b/reflex/components/el/constants/reflex.py index 05c298325..199edf569 100644 --- a/reflex/components/el/constants/reflex.py +++ b/reflex/components/el/constants/reflex.py @@ -48,4 +48,4 @@ PROP_TO_ELEMENTS = { ELEMENT_TO_PROPS = defaultdict(list) for prop, elements in PROP_TO_ELEMENTS.items(): for el in elements: - ELEMENT_TO_PROPS[el].append(prop) # type: ignore + ELEMENT_TO_PROPS[el].append(prop) diff --git a/reflex/components/el/elements/forms.py b/reflex/components/el/elements/forms.py index 3e2235721..51ad201b2 100644 --- a/reflex/components/el/elements/forms.py +++ b/reflex/components/el/elements/forms.py @@ -153,7 +153,7 @@ class Form(BaseHTML): target: Var[Union[str, int, bool]] # If true, the form will be cleared after submit. - reset_on_submit: Var[bool] = False # type: ignore + reset_on_submit: Var[bool] = Var.create(False) # The name used to make this form's submit handler function unique. handle_submit_unique_name: Var[str] @@ -405,7 +405,7 @@ class Input(BaseHTML): (value_var := Var.create(value))._var_type ): props["value"] = ternary_operation( - (value_var != Var.create(None)) # pyright: ignore [reportGeneralTypeIssues] + (value_var != Var.create(None)) # pyright: ignore [reportArgumentType] & (value_var != Var(_js_expr="undefined")), value, Var.create(""), diff --git a/reflex/components/markdown/markdown.py b/reflex/components/markdown/markdown.py index 7c65c0d43..686c49a64 100644 --- a/reflex/components/markdown/markdown.py +++ b/reflex/components/markdown/markdown.py @@ -65,8 +65,8 @@ def get_base_component_map() -> dict[str, Callable]: "h5": lambda value: Heading.create(value, as_="h5", size="2", margin_y="0.5em"), "h6": lambda value: Heading.create(value, as_="h6", size="1", margin_y="0.5em"), "p": lambda value: Text.create(value, margin_y="1em"), - "ul": lambda value: UnorderedList.create(value, margin_y="1em"), # type: ignore - "ol": lambda value: OrderedList.create(value, margin_y="1em"), # type: ignore + "ul": lambda value: UnorderedList.create(value, margin_y="1em"), + "ol": lambda value: OrderedList.create(value, margin_y="1em"), "li": lambda value: ListItem.create(value, margin_y="0.5em"), "a": lambda value: Link.create(value), "code": lambda value: Code.create(value), @@ -236,7 +236,7 @@ class Markdown(Component): ), }, *[ - component(_MOCK_ARG)._get_all_imports() # type: ignore + component(_MOCK_ARG)._get_all_imports() for component in self.component_map.values() ], ] @@ -327,7 +327,7 @@ const {_LANGUAGE!s} = match ? match[1] : ''; if tag != "codeblock" # For codeblock, the mapping for some cases returns an array of elements. Let's join them into a string. else ternary_operation( - ARRAY_ISARRAY.call(_CHILDREN), # type: ignore + ARRAY_ISARRAY.call(_CHILDREN), # pyright: ignore [reportArgumentType] _CHILDREN.to(list).join("\n"), _CHILDREN, ).to(str) @@ -425,7 +425,7 @@ const {_LANGUAGE!s} = match ? match[1] : ''; for _component in self.component_map.values(): comp = _component(_MOCK_ARG) hooks.update(comp._get_all_hooks()) - formatted_hooks = MACROS.module.renderHooks(hooks) # type: ignore + formatted_hooks = MACROS.module.renderHooks(hooks) # pyright: ignore [reportAttributeAccessIssue] return f""" function {self._get_component_map_name()} () {{ {formatted_hooks} diff --git a/reflex/components/moment/moment.py b/reflex/components/moment/moment.py index 80940d228..a5fe79f07 100644 --- a/reflex/components/moment/moment.py +++ b/reflex/components/moment/moment.py @@ -28,9 +28,9 @@ class MomentDelta: class Moment(NoSSRComponent): """The Moment component.""" - tag: str = "Moment" + tag: str | None = "Moment" is_default = True - library: str = "react-moment" + library: str | None = "react-moment" lib_dependencies: List[str] = ["moment"] # How often the date update (how often time update / 0 to disable). diff --git a/reflex/components/next/link.py b/reflex/components/next/link.py index 0f7c81296..187618a09 100644 --- a/reflex/components/next/link.py +++ b/reflex/components/next/link.py @@ -17,4 +17,4 @@ class NextLink(Component): href: Var[str] # Whether to pass the href prop to the child. - pass_href: Var[bool] = True # type: ignore + pass_href: Var[bool] = Var.create(True) diff --git a/reflex/components/plotly/plotly.py b/reflex/components/plotly/plotly.py index 68efd4545..c85423d35 100644 --- a/reflex/components/plotly/plotly.py +++ b/reflex/components/plotly/plotly.py @@ -18,8 +18,8 @@ try: Template = layout.Template except ImportError: console.warn("Plotly is not installed. Please run `pip install plotly`.") - Figure = Any # type: ignore - Template = Any # type: ignore + Figure = Any + Template = Any def _event_points_data_signature(e0: Var) -> Tuple[Var[List[Point]]]: @@ -102,13 +102,13 @@ class Plotly(NoSSRComponent): is_default = True # The figure to display. This can be a plotly figure or a plotly data json. - data: Var[Figure] # type: ignore + data: Var[Figure] # pyright: ignore [reportInvalidTypeForm] # The layout of the graph. layout: Var[Dict] # The template for visual appearance of the graph. - template: Var[Template] # type: ignore + template: Var[Template] # pyright: ignore [reportInvalidTypeForm] # The config of the graph. config: Var[Dict] diff --git a/reflex/components/props.py b/reflex/components/props.py index adce134fc..823036406 100644 --- a/reflex/components/props.py +++ b/reflex/components/props.py @@ -62,13 +62,13 @@ class NoExtrasAllowedProps(Base): try: super().__init__(**kwargs) except ValidationError as e: - invalid_fields = ", ".join([error["loc"][0] for error in e.errors()]) # type: ignore + invalid_fields = ", ".join([error["loc"][0] for error in e.errors()]) # pyright: ignore [reportCallIssue, reportArgumentType] supported_props_str = ", ".join(f'"{field}"' for field in self.get_fields()) raise InvalidPropValueError( f"Invalid prop(s) {invalid_fields} for {component_name!r}. Supported props are {supported_props_str}" ) from None - class Config: + class Config: # pyright: ignore [reportIncompatibleVariableOverride] """Pydantic config.""" arbitrary_types_allowed = True diff --git a/reflex/components/radix/__init__.pyi b/reflex/components/radix/__init__.pyi index f4e81666a..9a16627b5 100644 --- a/reflex/components/radix/__init__.pyi +++ b/reflex/components/radix/__init__.pyi @@ -55,7 +55,7 @@ from .themes.layout.container import container as container from .themes.layout.flex import flex as flex from .themes.layout.grid import grid as grid from .themes.layout.list import list_item as list_item -from .themes.layout.list import list_ns as list # noqa +from .themes.layout.list import list_ns as list # noqa: F401 from .themes.layout.list import ordered_list as ordered_list from .themes.layout.list import unordered_list as unordered_list from .themes.layout.section import section as section diff --git a/reflex/components/radix/primitives/drawer.py b/reflex/components/radix/primitives/drawer.py index 534b97ac1..b9056c9d0 100644 --- a/reflex/components/radix/primitives/drawer.py +++ b/reflex/components/radix/primitives/drawer.py @@ -83,7 +83,7 @@ class DrawerTrigger(DrawerComponent): alias = "Vaul" + tag # Defaults to true, if the first child acts as the trigger. - as_child: Var[bool] = True # type: ignore + as_child: Var[bool] = Var.create(True) @classmethod def create(cls, *children: Any, **props: Any) -> Component: diff --git a/reflex/components/radix/primitives/progress.py b/reflex/components/radix/primitives/progress.py index 72aee1038..5fcc52f1b 100644 --- a/reflex/components/radix/primitives/progress.py +++ b/reflex/components/radix/primitives/progress.py @@ -83,7 +83,7 @@ class ProgressIndicator(ProgressComponent): "&[data_state='loading']": { "transition": f"transform {DEFAULT_ANIMATION_DURATION}ms linear", }, - "transform": f"translateX(calc(-100% + ({self.value} / {self.max} * 100%)))", # type: ignore + "transform": f"translateX(calc(-100% + ({self.value} / {self.max} * 100%)))", "boxShadow": "inset 0 0 0 1px var(--gray-a5)", } diff --git a/reflex/components/radix/primitives/slider.py b/reflex/components/radix/primitives/slider.py index 68f39e32c..6136e3171 100644 --- a/reflex/components/radix/primitives/slider.py +++ b/reflex/components/radix/primitives/slider.py @@ -30,7 +30,7 @@ def on_value_event_spec( Returns: The event handler spec. """ - return (value,) # type: ignore + return (value,) class SliderRoot(SliderComponent): diff --git a/reflex/components/radix/themes/color_mode.py b/reflex/components/radix/themes/color_mode.py index e93a26ef6..2377a2422 100644 --- a/reflex/components/radix/themes/color_mode.py +++ b/reflex/components/radix/themes/color_mode.py @@ -115,12 +115,12 @@ class ColorModeIconButton(IconButton): Returns: The button component. """ - position = props.pop("position", None) + position: str | Var = props.pop("position", None) allow_system = props.pop("allow_system", False) # position is used to set nice defaults for positioning the icon button if isinstance(position, Var): - _set_var_default(props, position, "position", "fixed", position) # type: ignore + _set_var_default(props, position, "position", "fixed", position) # pyright: ignore [reportArgumentType] _set_var_default(props, position, "bottom", "2rem") _set_var_default(props, position, "top", "2rem") _set_var_default(props, position, "left", "2rem") diff --git a/reflex/components/radix/themes/components/radio_group.py b/reflex/components/radix/themes/components/radio_group.py index 80b3ee10c..f34c92159 100644 --- a/reflex/components/radix/themes/components/radio_group.py +++ b/reflex/components/radix/themes/components/radio_group.py @@ -155,7 +155,7 @@ class HighLevelRadioGroup(RadixThemesComponent): if isinstance(default_value, str) or ( isinstance(default_value, Var) and default_value._var_type is str ): - default_value = LiteralVar.create(default_value) # type: ignore + default_value = LiteralVar.create(default_value) else: default_value = LiteralVar.create(default_value).to_string() diff --git a/reflex/components/radix/themes/components/text_field.py b/reflex/components/radix/themes/components/text_field.py index c8bdab443..130fb7aed 100644 --- a/reflex/components/radix/themes/components/text_field.py +++ b/reflex/components/radix/themes/components/text_field.py @@ -105,7 +105,7 @@ class TextFieldRoot(elements.Input, RadixThemesComponent): (value_var := Var.create(value))._var_type ): props["value"] = ternary_operation( - (value_var != Var.create(None)) # pyright: ignore [reportGeneralTypeIssues] + (value_var != Var.create(None)) # pyright: ignore [reportArgumentType] & (value_var != Var(_js_expr="undefined")), value, Var.create(""), diff --git a/reflex/components/radix/themes/layout/__init__.pyi b/reflex/components/radix/themes/layout/__init__.pyi index 6712a3068..21fc8d921 100644 --- a/reflex/components/radix/themes/layout/__init__.pyi +++ b/reflex/components/radix/themes/layout/__init__.pyi @@ -9,7 +9,7 @@ from .container import container as container from .flex import flex as flex from .grid import grid as grid from .list import list_item as list_item -from .list import list_ns as list # noqa +from .list import list_ns as list # noqa: F401 from .list import ordered_list as ordered_list from .list import unordered_list as unordered_list from .section import section as section diff --git a/reflex/components/radix/themes/layout/list.py b/reflex/components/radix/themes/layout/list.py index a306e19a4..b79e99bf7 100644 --- a/reflex/components/radix/themes/layout/list.py +++ b/reflex/components/radix/themes/layout/list.py @@ -72,7 +72,7 @@ class BaseList(Component, MarkdownComponentMap): if isinstance(items, Var): children = [Foreach.create(items, ListItem.create)] else: - children = [ListItem.create(item) for item in items] # type: ignore + children = [ListItem.create(item) for item in items] props["direction"] = "column" style = props.setdefault("style", {}) style["list_style_type"] = list_style_type diff --git a/reflex/components/radix/themes/layout/stack.py b/reflex/components/radix/themes/layout/stack.py index d11c3488b..f017ff783 100644 --- a/reflex/components/radix/themes/layout/stack.py +++ b/reflex/components/radix/themes/layout/stack.py @@ -49,14 +49,14 @@ class VStack(Stack): """A vertical stack component.""" # The direction of the stack. - direction: Var[LiteralFlexDirection] = "column" # type: ignore + direction: Var[LiteralFlexDirection] = Var.create("column") class HStack(Stack): """A horizontal stack component.""" # The direction of the stack. - direction: Var[LiteralFlexDirection] = "row" # type: ignore + direction: Var[LiteralFlexDirection] = Var.create("row") stack = Stack.create diff --git a/reflex/components/radix/themes/typography/link.py b/reflex/components/radix/themes/typography/link.py index c93102408..09172b108 100644 --- a/reflex/components/radix/themes/typography/link.py +++ b/reflex/components/radix/themes/typography/link.py @@ -60,7 +60,7 @@ class Link(RadixThemesComponent, A, MemoizationLeaf, MarkdownComponentMap): Returns: The import dict. """ - return next_link._get_imports() # type: ignore + return next_link._get_imports() # pyright: ignore [reportReturnType] @classmethod def create(cls, *children, **props) -> Component: diff --git a/reflex/components/radix/themes/typography/text.py b/reflex/components/radix/themes/typography/text.py index 1663ddedf..cb6527915 100644 --- a/reflex/components/radix/themes/typography/text.py +++ b/reflex/components/radix/themes/typography/text.py @@ -47,7 +47,7 @@ class Text(elements.Span, RadixThemesComponent, MarkdownComponentMap): as_child: Var[bool] # Change the default rendered element into a semantically appropriate alternative (cannot be used with asChild) - as_: Var[LiteralType] = "p" # type: ignore + as_: Var[LiteralType] = Var.create("p") # Text size: "1" - "9" size: Var[Responsive[LiteralTextSize]] @@ -71,7 +71,7 @@ class Text(elements.Span, RadixThemesComponent, MarkdownComponentMap): class Span(Text): """A variant of text rendering as element.""" - as_: Var[LiteralType] = "span" # type: ignore + as_: Var[LiteralType] = Var.create("span") class Em(elements.Em, RadixThemesComponent): diff --git a/reflex/components/react_player/react_player.py b/reflex/components/react_player/react_player.py index fb0319ceb..7b7bb34e3 100644 --- a/reflex/components/react_player/react_player.py +++ b/reflex/components/react_player/react_player.py @@ -39,7 +39,7 @@ class ReactPlayer(NoSSRComponent): loop: Var[bool] # Set to true or false to display native player controls. - controls: Var[bool] = True # type: ignore + controls: Var[bool] = Var.create(True) # Set to true to show just the video thumbnail, which loads the full player on click light: Var[bool] diff --git a/reflex/components/recharts/charts.py b/reflex/components/recharts/charts.py index c25107dc0..6edfce58f 100644 --- a/reflex/components/recharts/charts.py +++ b/reflex/components/recharts/charts.py @@ -25,10 +25,10 @@ class ChartBase(RechartsCharts): """A component that wraps a Recharts charts.""" # The width of chart container. String or Integer - width: Var[Union[str, int]] = "100%" # type: ignore + width: Var[Union[str, int]] = Var.create("100%") # The height of chart container. - height: Var[Union[str, int]] = "100%" # type: ignore + height: Var[Union[str, int]] = Var.create("100%") # The customized event handler of click on the component in this chart on_click: EventHandler[no_args_event_spec] @@ -84,21 +84,19 @@ class ChartBase(RechartsCharts): cls._ensure_valid_dimension("width", width) cls._ensure_valid_dimension("height", height) - dim_props = { - "width": width if width is not None else "100%", - "height": height if height is not None else "100%", - } - # Ensure that the min_height and min_width are set to prevent the chart from collapsing. # We are using small values so that height and width can still be used over min_height and min_width. # Without this, sometimes the chart will not be visible. Causing confusion to the user. # With this, the user will see a small chart and can adjust the height and width and can figure out that the issue is with the size. - dim_props["min_height"] = props.pop("min_height", 10) - dim_props["min_width"] = props.pop("min_width", 10) + min_height = props.pop("min_height", 10) + min_width = props.pop("min_width", 10) return ResponsiveContainer.create( super().create(*children, **props), - **dim_props, # type: ignore + width=width if width is not None else "100%", + height=height if height is not None else "100%", + min_width=min_width, + min_height=min_height, ) @@ -460,10 +458,10 @@ class Treemap(RechartsCharts): alias = "RechartsTreemap" # The width of chart container. String or Integer. Default: "100%" - width: Var[Union[str, int]] = "100%" # type: ignore + width: Var[Union[str, int]] = Var.create("100%") # The height of chart container. String or Integer. Default: "100%" - height: Var[Union[str, int]] = "100%" # type: ignore + height: Var[Union[str, int]] = Var.create("100%") # data of treemap. Array data: Var[List[Dict[str, Any]]] diff --git a/reflex/components/recharts/polar.py b/reflex/components/recharts/polar.py index 7bb623d34..77aa1ef5e 100644 --- a/reflex/components/recharts/polar.py +++ b/reflex/components/recharts/polar.py @@ -64,7 +64,7 @@ class Pie(Recharts): legend_type: Var[LiteralLegendType] # If false set, labels will not be drawn. If true set, labels will be drawn which have the props calculated internally. Default: False - label: Var[bool] = False # type: ignore + label: Var[bool] = Var.create(False) # If false set, label lines will not be drawn. If true set, label lines will be drawn which have the props calculated internally. Default: False label_line: Var[bool] diff --git a/reflex/components/sonner/toast.py b/reflex/components/sonner/toast.py index 7177c6473..0f666fd64 100644 --- a/reflex/components/sonner/toast.py +++ b/reflex/components/sonner/toast.py @@ -142,7 +142,7 @@ class ToastProps(PropsBase, NoExtrasAllowedProps): Returns: The object as a dictionary with ToastAction fields intact. """ - kwargs.setdefault("exclude_none", True) # type: ignore + kwargs.setdefault("exclude_none", True) d = super().dict(*args, **kwargs) # Keep these fields as ToastAction so they can be serialized specially if "action" in d: @@ -167,7 +167,7 @@ class ToastProps(PropsBase, NoExtrasAllowedProps): class Toaster(Component): """A Toaster Component for displaying toast notifications.""" - library: str = "sonner@1.7.2" + library: str | None = "sonner@1.7.2" tag = "Toaster" @@ -222,6 +222,8 @@ class Toaster(Component): Returns: The hooks for the toaster component. """ + if self.library is None: + return [] hook = Var( _js_expr=f"{toast_ref} = toast", _var_data=VarData( @@ -266,7 +268,7 @@ class Toaster(Component): raise ValueError("Toast message or title or description must be provided.") if props: - args = LiteralVar.create(ToastProps(component_name="rx.toast", **props)) # pyright: ignore [reportCallIssue, reportGeneralTypeIssues] + args = LiteralVar.create(ToastProps(component_name="rx.toast", **props)) # pyright: ignore [reportCallIssue] toast = toast_command.call(message, args) else: toast = toast_command.call(message) diff --git a/reflex/components/tags/iter_tag.py b/reflex/components/tags/iter_tag.py index 38ecaf81c..cb02ca000 100644 --- a/reflex/components/tags/iter_tag.py +++ b/reflex/components/tags/iter_tag.py @@ -41,14 +41,14 @@ class IterTag(Tag): try: if iterable._var_type.mro()[0] is dict: # Arg is a tuple of (key, value). - return Tuple[get_args(iterable._var_type)] # type: ignore + return Tuple[get_args(iterable._var_type)] # pyright: ignore [reportReturnType] elif iterable._var_type.mro()[0] is tuple: # Arg is a union of any possible values in the tuple. - return Union[get_args(iterable._var_type)] # type: ignore + return Union[get_args(iterable._var_type)] # pyright: ignore [reportReturnType] else: return get_args(iterable._var_type)[0] except Exception: - return Any + return Any # pyright: ignore [reportReturnType] def get_index_var(self) -> Var: """Get the index var for the tag (with curly braces). diff --git a/reflex/config.py b/reflex/config.py index c3c5e4cf5..a76bf987d 100644 --- a/reflex/config.py +++ b/reflex/config.py @@ -390,7 +390,7 @@ class EnvVar(Generic[T]): os.environ[self.name] = str(value) -class env_var: # type: ignore # noqa: N801 +class env_var: # noqa: N801 # pyright: ignore [reportRedeclaration] """Descriptor for environment variables.""" name: str @@ -600,7 +600,7 @@ class Config(Base): See the [configuration](https://reflex.dev/docs/getting-started/configuration/) docs for more info. """ - class Config: + class Config: # pyright: ignore [reportIncompatibleVariableOverride] """Pydantic config for the config.""" validate_assignment = True @@ -766,7 +766,7 @@ class Config(Base): """ if self.env_file: try: - from dotenv import load_dotenv # type: ignore + from dotenv import load_dotenv # pyright: ignore [reportMissingImports] # load env file if exists load_dotenv(self.env_file, override=True) diff --git a/reflex/custom_components/custom_components.py b/reflex/custom_components/custom_components.py index 8000e7f4c..3bfbb1580 100644 --- a/reflex/custom_components/custom_components.py +++ b/reflex/custom_components/custom_components.py @@ -925,7 +925,7 @@ def _get_file_from_prompt_in_loop() -> Tuple[bytes, str] | None: image_file = file_extension = None while image_file is None: image_filepath = Path( - console.ask("Upload a preview image of your demo app (enter to skip)") + console.ask("Upload a preview image of your demo app (enter to skip)") # pyright: ignore [reportArgumentType] ) if not image_filepath: break diff --git a/reflex/event.py b/reflex/event.py index 96c2c30b9..0fc874b38 100644 --- a/reflex/event.py +++ b/reflex/event.py @@ -263,7 +263,7 @@ class EventSpec(EventActionsMixin): """ # The event handler. - handler: EventHandler = dataclasses.field(default=None) # type: ignore + handler: EventHandler = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType] # The handler on the client to process event. client_handler_name: str = dataclasses.field(default="") @@ -589,7 +589,7 @@ def no_args_event_spec() -> Tuple[()]: Returns: An empty tuple. """ - return () # type: ignore + return () # These chains can be used for their side effects when no other events are desired. @@ -617,9 +617,9 @@ class IdentityEventReturn(Generic[T], Protocol): @overload -def passthrough_event_spec( +def passthrough_event_spec( # pyright: ignore [reportOverlappingOverload] event_type: Type[T], / -) -> Callable[[Var[T]], Tuple[Var[T]]]: ... # type: ignore +) -> Callable[[Var[T]], Tuple[Var[T]]]: ... @overload @@ -632,7 +632,7 @@ def passthrough_event_spec( def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: ... -def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: # type: ignore +def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: # pyright: ignore [reportInconsistentOverload] """A helper function that returns the input event as output. Args: @@ -646,9 +646,9 @@ def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: # return values inner_type = tuple(Var[event_type] for event_type in event_types) - return_annotation = Tuple[inner_type] # type: ignore + return_annotation = Tuple[inner_type] - inner.__signature__ = inspect.signature(inner).replace( # type: ignore + inner.__signature__ = inspect.signature(inner).replace( # pyright: ignore [reportFunctionMemberAccess] parameters=[ inspect.Parameter( f"ev_{i}", @@ -730,7 +730,7 @@ class FileUpload: # Call the lambda to get the event chain. events = call_event_fn( on_upload_progress, self.on_upload_progress_args_spec - ) # type: ignore + ) else: raise ValueError(f"{on_upload_progress} is not a valid event handler.") if isinstance(events, Var): @@ -777,7 +777,7 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec: return None fn.__qualname__ = name - fn.__signature__ = sig + fn.__signature__ = sig # pyright: ignore [reportFunctionMemberAccess] return EventSpec( handler=EventHandler(fn=fn, state_full_name=FRONTEND_EVENT_STATE), args=tuple( @@ -1050,13 +1050,13 @@ def download( is_data_url = (data.js_type() == "string") & ( data.to(str).startswith("data:") - ) # type: ignore + ) # If it's a data: URI, use it as is, otherwise convert the Var to JSON in a data: URI. - url = cond( # type: ignore + url = cond( is_data_url, data.to(str), - "data:text/plain," + data.to_string(), # type: ignore + "data:text/plain," + data.to_string(), ) elif isinstance(data, bytes): # Caller provided bytes, so base64 encode it as a data: URI. @@ -1230,7 +1230,7 @@ def call_event_handler( #noqa: DAR401 """ - event_spec_args = parse_args_spec(event_spec) # type: ignore + event_spec_args = parse_args_spec(event_spec) if isinstance(event_callback, EventSpec): check_fn_match_arg_spec( @@ -1340,7 +1340,7 @@ def call_event_handler( if delayed_exceptions: raise delayed_exceptions[0] - return event_callback(*event_spec_args) # type: ignore + return event_callback(*event_spec_args) def unwrap_var_annotation(annotation: GenericType): @@ -1574,7 +1574,7 @@ def fix_events( if not isinstance(e, EventSpec): raise ValueError(f"Unexpected event type, {type(e)}.") name = format.format_event_handler(e.handler) - payload = {k._js_expr: v._decode() for k, v in e.args} # type: ignore + payload = {k._js_expr: v._decode() for k, v in e.args} # Filter router_data to reduce payload size event_router_data = { @@ -1623,7 +1623,7 @@ class EventVar(ObjectVar, python_types=EventSpec): class LiteralEventVar(VarOperationCall, LiteralVar, EventVar): """A literal event var.""" - _var_value: EventSpec = dataclasses.field(default=None) # type: ignore + _var_value: EventSpec = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType] def __hash__(self) -> int: """Get the hash of the var. @@ -1687,7 +1687,7 @@ class EventChainVar(BuilderFunctionVar, python_types=EventChain): class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainVar): """A literal event chain var.""" - _var_value: EventChain = dataclasses.field(default=None) # type: ignore + _var_value: EventChain = dataclasses.field(default=None) # pyright: ignore [reportAssignmentType] def __hash__(self) -> int: """Get the hash of the var. @@ -1717,7 +1717,7 @@ class LiteralEventChainVar(ArgsFunctionOperationBuilder, LiteralVar, EventChainV if isinstance(value.args_spec, Sequence) else value.args_spec ) - sig = inspect.signature(arg_spec) # type: ignore + sig = inspect.signature(arg_spec) # pyright: ignore [reportArgumentType] if sig.parameters: arg_def = tuple((f"_{p}" for p in sig.parameters)) arg_def_expr = LiteralVar.create([Var(_js_expr=arg) for arg in arg_def]) @@ -1819,7 +1819,7 @@ class EventCallback(Generic[P, T]): value4: V4 | Var[V4], ) -> EventCallback[Q, T]: ... - def __call__(self, *values) -> EventCallback: # type: ignore + def __call__(self, *values) -> EventCallback: # pyright: ignore [reportInconsistentOverload] """Call the function with the values. Args: @@ -1828,7 +1828,7 @@ class EventCallback(Generic[P, T]): Returns: The function with the values. """ - return self.func(*values) # type: ignore + return self.func(*values) # pyright: ignore [reportCallIssue, reportReturnType] @overload def __get__( @@ -1838,7 +1838,7 @@ class EventCallback(Generic[P, T]): @overload def __get__(self, instance, owner) -> Callable[P, T]: ... - def __get__(self, instance, owner) -> Callable: # type: ignore + def __get__(self, instance, owner) -> Callable: """Get the function with the instance bound to it. Args: @@ -1849,9 +1849,9 @@ class EventCallback(Generic[P, T]): The function with the instance bound to it """ if instance is None: - return self.func # type: ignore + return self.func - return partial(self.func, instance) # type: ignore + return partial(self.func, instance) G = ParamSpec("G") @@ -1902,7 +1902,7 @@ class EventNamespace(types.SimpleNamespace): @staticmethod def __call__( func: None = None, *, background: bool | None = None - ) -> Callable[[Callable[Concatenate[BASE_STATE, P], T]], EventCallback[P, T]]: ... + ) -> Callable[[Callable[Concatenate[BASE_STATE, P], T]], EventCallback[P, T]]: ... # pyright: ignore [reportInvalidTypeVarUse] @overload @staticmethod @@ -1945,7 +1945,7 @@ class EventNamespace(types.SimpleNamespace): "Background task must be async function or generator." ) setattr(func, BACKGROUND_TASK_MARKER, True) - return func # type: ignore + return func # pyright: ignore [reportReturnType] if func is not None: return wrapper(func) diff --git a/reflex/experimental/client_state.py b/reflex/experimental/client_state.py index ca91905ae..ce3a941bb 100644 --- a/reflex/experimental/client_state.py +++ b/reflex/experimental/client_state.py @@ -201,9 +201,7 @@ class ClientStateVar(Var): ) .to(self._var_type) ._replace( - merge_var_data=VarData( # type: ignore - imports=_refs_import if self._global_ref else {} - ) + merge_var_data=VarData(imports=_refs_import if self._global_ref else {}) ) ) diff --git a/reflex/experimental/layout.py b/reflex/experimental/layout.py index e5a1bab04..1c74271b2 100644 --- a/reflex/experimental/layout.py +++ b/reflex/experimental/layout.py @@ -44,10 +44,10 @@ class Sidebar(Box, MemoizationLeaf): Returns: The style of the component. """ - sidebar: Component = self.children[-2] # type: ignore - spacer: Component = self.children[-1] # type: ignore + sidebar: Component = self.children[-2] # pyright: ignore [reportAssignmentType] + spacer: Component = self.children[-1] # pyright: ignore [reportAssignmentType] open = ( - self.State.open # type: ignore + self.State.open # pyright: ignore [reportAttributeAccessIssue] if self.State else Var(_js_expr="open") ) @@ -159,11 +159,11 @@ class SidebarTrigger(Fragment): """ trigger_props = {**props, **sidebar_trigger_style} - inner_sidebar: Component = sidebar.children[0] # type: ignore + inner_sidebar: Component = sidebar.children[0] # pyright: ignore [reportAssignmentType] sidebar_width = inner_sidebar.style.get("width") if sidebar.State: - open, toggle = sidebar.State.open, sidebar.State.toggle # type: ignore + open, toggle = sidebar.State.open, sidebar.State.toggle # pyright: ignore [reportAttributeAccessIssue] else: open, toggle = ( Var(_js_expr="open"), diff --git a/reflex/model.py b/reflex/model.py index 295159de0..6e44498e9 100644 --- a/reflex/model.py +++ b/reflex/model.py @@ -242,7 +242,7 @@ class ModelRegistry: return metadata -class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssues] +class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssues,reportIncompatibleVariableOverride] """Base class to define a table in the database.""" # The primary key for the table. @@ -415,7 +415,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue connection=connection, target_metadata=ModelRegistry.get_metadata(), render_item=cls._alembic_render_item, - process_revision_directives=writer, # type: ignore + process_revision_directives=writer, compare_type=False, render_as_batch=True, # for sqlite compatibility ) diff --git a/reflex/reflex.py b/reflex/reflex.py index 34a4a58a5..2fb10a944 100644 --- a/reflex/reflex.py +++ b/reflex/reflex.py @@ -17,7 +17,7 @@ from reflex.state import reset_disk_state_manager from reflex.utils import console, telemetry # Disable typer+rich integration for help panels -typer.core.rich = None # type: ignore +typer.core.rich = None # pyright: ignore [reportPrivateImportUsage] # Create the app. try: @@ -355,7 +355,7 @@ def logout( check_version() - logout(loglevel) # type: ignore + logout(loglevel) # pyright: ignore [reportArgumentType] db_cli = typer.Typer() diff --git a/reflex/state.py b/reflex/state.py index be3deda78..badc40dfd 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -587,7 +587,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): if cls._item_is_event_handler(name, fn) } - for mixin in cls._mixins(): + for mixin in cls._mixins(): # pyright: ignore [reportAssignmentType] for name, value in mixin.__dict__.items(): if name in cls.inherited_vars: continue @@ -599,7 +599,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): cls.computed_vars[newcv._js_expr] = newcv cls.vars[newcv._js_expr] = newcv continue - if types.is_backend_base_variable(name, mixin): + if types.is_backend_base_variable(name, mixin): # pyright: ignore [reportArgumentType] cls.backend_vars[name] = copy.deepcopy(value) continue if events.get(name) is not None: @@ -899,7 +899,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): ] if len(parent_states) >= 2: raise ValueError(f"Only one parent state is allowed {parent_states}.") - return parent_states[0] if len(parent_states) == 1 else None # type: ignore + return parent_states[0] if len(parent_states) == 1 else None @classmethod def get_substates(cls) -> set[Type[BaseState]]: @@ -1268,8 +1268,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): fn = _no_chain_background_task(type(self), name, handler.fn) else: fn = functools.partial(handler.fn, self) - fn.__module__ = handler.fn.__module__ # type: ignore - fn.__qualname__ = handler.fn.__qualname__ # type: ignore + fn.__module__ = handler.fn.__module__ + fn.__qualname__ = handler.fn.__qualname__ return fn backend_vars = super().__getattribute__("_backend_vars") @@ -1634,7 +1634,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): """ # Oopsie case: you didn't give me a Var... so get what you give. if not isinstance(var, Var): - return var # type: ignore + return var # Fast case: this is a literal var and the value is known. if hasattr(var, "_var_value"): @@ -2453,7 +2453,7 @@ class OnLoadInternalState(State): self.router.session.client_token, router_data=self.router_data, ), - State.set_is_hydrated(True), # type: ignore + State.set_is_hydrated(True), # pyright: ignore [reportAttributeAccessIssue] ] @@ -2737,7 +2737,7 @@ class StateProxy(wrapt.ObjectProxy): # ensure mutations to these containers are blocked unless proxy is _mutable return ImmutableMutableProxy( wrapped=value.__wrapped__, - state=self, # type: ignore + state=self, field_name=value._self_field_name, ) if isinstance(value, functools.partial) and value.args[0] is self.__wrapped__: @@ -2750,7 +2750,7 @@ class StateProxy(wrapt.ObjectProxy): ) if isinstance(value, MethodType) and value.__self__ is self.__wrapped__: # Rebind methods to the proxy instance - value = type(value)(value.__func__, self) # type: ignore + value = type(value)(value.__func__, self) return value def __setattr__(self, name: str, value: Any) -> None: @@ -2950,7 +2950,7 @@ class StateManagerMemory(StateManager): # The dict of mutexes for each client _states_locks: Dict[str, asyncio.Lock] = pydantic.PrivateAttr({}) - class Config: + class Config: # pyright: ignore [reportIncompatibleVariableOverride] """The Pydantic config.""" fields = { @@ -3068,7 +3068,7 @@ class StateManagerDisk(StateManager): # The token expiration time (s). token_expiration: int = pydantic.Field(default_factory=_default_token_expiration) - class Config: + class Config: # pyright: ignore [reportIncompatibleVariableOverride] """The Pydantic config.""" fields = { @@ -3776,9 +3776,9 @@ class MutableProxy(wrapt.ObjectProxy): wrapper_cls_name, (cls,), { - dataclasses._FIELDS: getattr( # pyright: ignore [reportGeneralTypeIssues] + dataclasses._FIELDS: getattr( # pyright: ignore [reportAttributeAccessIssue] wrapped_cls, - dataclasses._FIELDS, # pyright: ignore [reportGeneralTypeIssues] + dataclasses._FIELDS, # pyright: ignore [reportAttributeAccessIssue] ), }, ) @@ -3931,7 +3931,7 @@ class MutableProxy(wrapt.ObjectProxy): ): # Wrap methods called on Base subclasses, which might do _anything_ return wrapt.FunctionWrapper( - functools.partial(value.__func__, self), + functools.partial(value.__func__, self), # pyright: ignore [reportFunctionMemberAccess] self._wrap_recursive_decorator, ) diff --git a/reflex/style.py b/reflex/style.py index 3916bbc7c..5142d0181 100644 --- a/reflex/style.py +++ b/reflex/style.py @@ -78,7 +78,7 @@ def set_color_mode( _var_data=VarData.merge( base_setter._get_all_var_data(), new_color_mode._get_all_var_data() ), - ).to(FunctionVar, EventChain) # type: ignore + ).to(FunctionVar, EventChain) # Var resolves to the current color mode for the app ("light", "dark" or "system") diff --git a/reflex/testing.py b/reflex/testing.py index 7c6aab93b..897cb3424 100644 --- a/reflex/testing.py +++ b/reflex/testing.py @@ -80,7 +80,7 @@ T = TypeVar("T") TimeoutType = Optional[Union[int, float]] if platform.system() == "Windows": - FRONTEND_POPEN_ARGS["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP # type: ignore + FRONTEND_POPEN_ARGS["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP # pyright: ignore [reportAttributeAccessIssue] FRONTEND_POPEN_ARGS["shell"] = True else: FRONTEND_POPEN_ARGS["start_new_session"] = True @@ -258,7 +258,7 @@ class AppHarness: if self.app_source is not None: app_globals = self._get_globals_from_signature(self.app_source) if isinstance(self.app_source, functools.partial): - self.app_source = self.app_source.func # type: ignore + self.app_source = self.app_source.func # get the source from a function or module object source_code = "\n".join( [ @@ -294,11 +294,15 @@ class AppHarness: if p not in before_decorated_pages ] self.app_instance = self.app_module.app - if isinstance(self.app_instance._state_manager, StateManagerRedis): + if self.app_instance and isinstance( + self.app_instance._state_manager, StateManagerRedis + ): # Create our own redis connection for testing. - self.state_manager = StateManagerRedis.create(self.app_instance._state) + self.state_manager = StateManagerRedis.create(self.app_instance._state) # pyright: ignore [reportArgumentType] else: - self.state_manager = self.app_instance._state_manager + self.state_manager = ( + self.app_instance._state_manager if self.app_instance else None + ) def _reload_state_module(self): """Reload the rx.State module to avoid conflict when reloading.""" @@ -621,23 +625,23 @@ class AppHarness: want_headless = True if driver_clz is None: requested_driver = environment.APP_HARNESS_DRIVER.get() - driver_clz = getattr(webdriver, requested_driver) + driver_clz = getattr(webdriver, requested_driver) # pyright: ignore [reportPossiblyUnboundVariable] if driver_options is None: - driver_options = getattr(webdriver, f"{requested_driver}Options")() - if driver_clz is webdriver.Chrome: + driver_options = getattr(webdriver, f"{requested_driver}Options")() # pyright: ignore [reportPossiblyUnboundVariable] + if driver_clz is webdriver.Chrome: # pyright: ignore [reportPossiblyUnboundVariable] if driver_options is None: - driver_options = webdriver.ChromeOptions() + driver_options = webdriver.ChromeOptions() # pyright: ignore [reportPossiblyUnboundVariable] driver_options.add_argument("--class=AppHarness") if want_headless: driver_options.add_argument("--headless=new") - elif driver_clz is webdriver.Firefox: + elif driver_clz is webdriver.Firefox: # pyright: ignore [reportPossiblyUnboundVariable] if driver_options is None: - driver_options = webdriver.FirefoxOptions() + driver_options = webdriver.FirefoxOptions() # pyright: ignore [reportPossiblyUnboundVariable] if want_headless: driver_options.add_argument("-headless") - elif driver_clz is webdriver.Edge: + elif driver_clz is webdriver.Edge: # pyright: ignore [reportPossiblyUnboundVariable] if driver_options is None: - driver_options = webdriver.EdgeOptions() + driver_options = webdriver.EdgeOptions() # pyright: ignore [reportPossiblyUnboundVariable] if want_headless: driver_options.add_argument("headless") if driver_options is None: @@ -653,7 +657,7 @@ class AppHarness: driver_options.set_capability(key, value) if driver_kwargs is None: driver_kwargs = {} - driver = driver_clz(options=driver_options, **driver_kwargs) # type: ignore + driver = driver_clz(options=driver_options, **driver_kwargs) # pyright: ignore [reportOptionalCall, reportArgumentType] driver.get(self.frontend_url) self._frontends.append(driver) return driver @@ -885,8 +889,8 @@ class Subdir404TCPServer(socketserver.TCPServer): request, client_address, self, - directory=str(self.root), # type: ignore - error_page_map=self.error_page_map, # type: ignore + directory=str(self.root), # pyright: ignore [reportCallIssue] + error_page_map=self.error_page_map, # pyright: ignore [reportCallIssue] ) diff --git a/reflex/utils/compat.py b/reflex/utils/compat.py index e63492a6b..339911063 100644 --- a/reflex/utils/compat.py +++ b/reflex/utils/compat.py @@ -50,11 +50,11 @@ def pydantic_v1_patch(): ] originals = {module: sys.modules.get(module) for module in patched_modules} try: - import pydantic.v1 # type: ignore + import pydantic.v1 - sys.modules["pydantic.fields"] = pydantic.v1.fields # type: ignore - sys.modules["pydantic.main"] = pydantic.v1.main # type: ignore - sys.modules["pydantic.errors"] = pydantic.v1.errors # type: ignore + sys.modules["pydantic.fields"] = pydantic.v1.fields # pyright: ignore [reportAttributeAccessIssue] + sys.modules["pydantic.main"] = pydantic.v1.main # pyright: ignore [reportAttributeAccessIssue] + sys.modules["pydantic.errors"] = pydantic.v1.errors # pyright: ignore [reportAttributeAccessIssue] sys.modules["pydantic"] = pydantic.v1 yield except (ImportError, AttributeError): diff --git a/reflex/utils/console.py b/reflex/utils/console.py index 900e5ed07..d5b7a0d6e 100644 --- a/reflex/utils/console.py +++ b/reflex/utils/console.py @@ -196,7 +196,7 @@ def _get_first_non_framework_frame() -> FrameType | None: exclude_modules = [click, rx, typer, typing_extensions] exclude_roots = [ p.parent.resolve() - if (p := Path(m.__file__)).name == "__init__.py" + if (p := Path(m.__file__)).name == "__init__.py" # pyright: ignore [reportArgumentType] else p.resolve() for m in exclude_modules ] @@ -275,7 +275,7 @@ def ask( choices: list[str] | None = None, default: str | None = None, show_choices: bool = True, -) -> str: +) -> str | None: """Takes a prompt question and optionally a list of choices and returns the user input. @@ -290,7 +290,7 @@ def ask( """ return Prompt.ask( question, choices=choices, default=default, show_choices=show_choices - ) # type: ignore + ) def progress(): diff --git a/reflex/utils/exec.py b/reflex/utils/exec.py index 1e5cda10b..22322634d 100644 --- a/reflex/utils/exec.py +++ b/reflex/utils/exec.py @@ -71,7 +71,7 @@ def notify_backend(): # run_process_and_launch_url is assumed to be used # only to launch the frontend # If this is not the case, might have to change the logic -def run_process_and_launch_url(run_command: list[str], backend_present=True): +def run_process_and_launch_url(run_command: list[str | None], backend_present=True): """Run the process and launch the URL. Args: @@ -89,7 +89,7 @@ def run_process_and_launch_url(run_command: list[str], backend_present=True): if process is None: kwargs = {} if constants.IS_WINDOWS and backend_present: - kwargs["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP # type: ignore + kwargs["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP # pyright: ignore [reportAttributeAccessIssue] process = processes.new_process( run_command, cwd=get_web_dir(), @@ -151,7 +151,7 @@ def run_frontend(root: Path, port: str, backend_present=True): console.rule("[bold green]App Running") os.environ["PORT"] = str(get_config().frontend_port if port is None else port) run_process_and_launch_url( - [prerequisites.get_package_manager(), "run", "dev"], # type: ignore + [prerequisites.get_package_manager(), "run", "dev"], backend_present, ) @@ -173,7 +173,7 @@ def run_frontend_prod(root: Path, port: str, backend_present=True): # Run the frontend in production mode. console.rule("[bold green]App Running") run_process_and_launch_url( - [prerequisites.get_package_manager(), "run", "prod"], # type: ignore + [prerequisites.get_package_manager(), "run", "prod"], backend_present, ) @@ -295,9 +295,11 @@ def run_granian_backend(host, port, loglevel: LogLevel): """ console.debug("Using Granian for backend") try: - from granian import Granian # type: ignore - from granian.constants import Interfaces # type: ignore - from granian.log import LogLevels # type: ignore + from granian import Granian # pyright: ignore [reportMissingImports] + from granian.constants import ( # pyright: ignore [reportMissingImports] + Interfaces, + ) + from granian.log import LogLevels # pyright: ignore [reportMissingImports] Granian( target=get_granian_target(), @@ -413,7 +415,9 @@ def run_granian_backend_prod(host, port, loglevel): from reflex.utils import processes try: - from granian.constants import Interfaces # type: ignore + from granian.constants import ( # pyright: ignore [reportMissingImports] + Interfaces, + ) command = [ "granian", @@ -482,7 +486,7 @@ def output_system_info(): dependencies.append(fnm_info) if system == "Linux": - import distro # type: ignore + import distro os_version = distro.name(pretty=True) else: @@ -494,11 +498,11 @@ def output_system_info(): console.debug(f"{dep}") console.debug( - f"Using package installer at: {prerequisites.get_install_package_manager(on_failure_return_none=True)}" # type: ignore + f"Using package installer at: {prerequisites.get_install_package_manager(on_failure_return_none=True)}" ) console.debug( f"Using package executer at: {prerequisites.get_package_manager(on_failure_return_none=True)}" - ) # type: ignore + ) if system != "Windows": console.debug(f"Unzip path: {path_ops.which('unzip')}") diff --git a/reflex/utils/format.py b/reflex/utils/format.py index 87d160553..7973549b0 100644 --- a/reflex/utils/format.py +++ b/reflex/utils/format.py @@ -377,7 +377,7 @@ def format_prop( # For dictionaries, convert any properties to strings. elif isinstance(prop, dict): - prop = serializers.serialize_dict(prop) # type: ignore + prop = serializers.serialize_dict(prop) # pyright: ignore [reportAttributeAccessIssue] else: # Dump the prop as JSON. @@ -533,14 +533,14 @@ def format_queue_events( from reflex.vars import FunctionVar, Var if not events: - return Var("(() => null)").to(FunctionVar, EventChain) # type: ignore + return Var("(() => null)").to(FunctionVar, EventChain) # If no spec is provided, the function will take no arguments. def _default_args_spec(): return [] # Construct the arguments that the function accepts. - sig = inspect.signature(args_spec or _default_args_spec) # type: ignore + sig = inspect.signature(args_spec or _default_args_spec) if sig.parameters: arg_def = ",".join(f"_{p}" for p in sig.parameters) arg_def = f"({arg_def})" @@ -557,7 +557,7 @@ def format_queue_events( if isinstance(spec, (EventHandler, EventSpec)): specs = [call_event_handler(spec, args_spec or _default_args_spec)] elif isinstance(spec, type(lambda: None)): - specs = call_event_fn(spec, args_spec or _default_args_spec) # type: ignore + specs = call_event_fn(spec, args_spec or _default_args_spec) # pyright: ignore [reportAssignmentType, reportArgumentType] if isinstance(specs, Var): raise ValueError( f"Invalid event spec: {specs}. Expected a list of EventSpecs." @@ -569,7 +569,7 @@ def format_queue_events( return Var( f"{arg_def} => {{queueEvents([{','.join(payloads)}], {constants.CompileVars.SOCKET}); " f"processEvent({constants.CompileVars.SOCKET})}}", - ).to(FunctionVar, EventChain) # type: ignore + ).to(FunctionVar, EventChain) def format_query_params(router_data: dict[str, Any]) -> dict[str, str]: diff --git a/reflex/utils/imports.py b/reflex/utils/imports.py index ab217087c..46e8e7362 100644 --- a/reflex/utils/imports.py +++ b/reflex/utils/imports.py @@ -122,7 +122,7 @@ class ImportVar: """ if self.alias: return ( - self.alias if self.is_default else " as ".join([self.tag, self.alias]) # type: ignore + self.alias if self.is_default else " as ".join([self.tag, self.alias]) # pyright: ignore [reportCallIssue,reportArgumentType] ) else: return self.tag or "" diff --git a/reflex/utils/prerequisites.py b/reflex/utils/prerequisites.py index 66c9156a9..edaa77aba 100644 --- a/reflex/utils/prerequisites.py +++ b/reflex/utils/prerequisites.py @@ -176,7 +176,7 @@ def get_node_version() -> version.Version | None: try: result = processes.new_process([node_path, "-v"], run=True) # The output will be in the form "vX.Y.Z", but version.parse() can handle it - return version.parse(result.stdout) # type: ignore + return version.parse(result.stdout) # pyright: ignore [reportArgumentType] except (FileNotFoundError, TypeError): return None @@ -189,7 +189,7 @@ def get_fnm_version() -> version.Version | None: """ try: result = processes.new_process([constants.Fnm.EXE, "--version"], run=True) - return version.parse(result.stdout.split(" ")[1]) # type: ignore + return version.parse(result.stdout.split(" ")[1]) # pyright: ignore [reportOptionalMemberAccess, reportAttributeAccessIssue] except (FileNotFoundError, TypeError): return None except version.InvalidVersion as e: @@ -211,7 +211,7 @@ def get_bun_version() -> version.Version | None: try: # Run the bun -v command and capture the output result = processes.new_process([str(bun_path), "-v"], run=True) - return version.parse(str(result.stdout)) + return version.parse(str(result.stdout)) # pyright: ignore [reportArgumentType] except FileNotFoundError: return None except version.InvalidVersion as e: @@ -1188,7 +1188,7 @@ def install_frontend_packages(packages: set[str], config: Config): ) processes.run_process_with_fallback( - [install_package_manager, "install"], # type: ignore + [install_package_manager, "install"], fallback=fallback_command, analytics_enabled=True, show_status_message="Installing base frontend packages", @@ -1481,7 +1481,7 @@ def prompt_for_template_options(templates: list[Template]) -> str: ) # Return the template. - return templates[int(template)].name + return templates[int(template)].name # pyright: ignore [reportArgumentType] def fetch_app_templates(version: str) -> dict[str, Template]: diff --git a/reflex/utils/processes.py b/reflex/utils/processes.py index 575688eda..94e0fda3e 100644 --- a/reflex/utils/processes.py +++ b/reflex/utils/processes.py @@ -62,7 +62,7 @@ def get_process_on_port(port) -> Optional[psutil.Process]: psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess ): if importlib.metadata.version("psutil") >= "6.0.0": - conns = proc.net_connections(kind="inet") # type: ignore + conns = proc.net_connections(kind="inet") else: conns = proc.connections(kind="inet") for conn in conns: @@ -91,7 +91,7 @@ def kill_process_on_port(port): """ if get_process_on_port(port) is not None: with contextlib.suppress(psutil.AccessDenied): - get_process_on_port(port).kill() # type: ignore + get_process_on_port(port).kill() # pyright: ignore [reportOptionalMemberAccess] def change_port(port: str, _type: str) -> str: @@ -212,14 +212,14 @@ def run_concurrently_context( return # Convert the functions to tuples. - fns = [fn if isinstance(fn, tuple) else (fn,) for fn in fns] # type: ignore + fns = [fn if isinstance(fn, tuple) else (fn,) for fn in fns] # pyright: ignore [reportAssignmentType] # Run the functions concurrently. executor = None try: executor = futures.ThreadPoolExecutor(max_workers=len(fns)) # Submit the tasks. - tasks = [executor.submit(*fn) for fn in fns] # type: ignore + tasks = [executor.submit(*fn) for fn in fns] # pyright: ignore [reportArgumentType] # Yield control back to the main thread while tasks are running. yield tasks diff --git a/reflex/utils/pyi_generator.py b/reflex/utils/pyi_generator.py index 152c06949..5a8cad18e 100644 --- a/reflex/utils/pyi_generator.py +++ b/reflex/utils/pyi_generator.py @@ -229,7 +229,7 @@ def _generate_imports( """ return [ *[ - ast.ImportFrom(module=name, names=[ast.alias(name=val) for val in values]) + ast.ImportFrom(module=name, names=[ast.alias(name=val) for val in values]) # pyright: ignore [reportCallIssue] for name, values in DEFAULT_IMPORTS.items() ], ast.Import([ast.alias("reflex")]), @@ -367,7 +367,7 @@ def _extract_class_props_as_ast_nodes( # Try to get default from pydantic field definition. default = target_class.__fields__[name].default if isinstance(default, Var): - default = default._decode() # type: ignore + default = default._decode() kwargs.append( ( @@ -434,10 +434,12 @@ def type_to_ast(typ, cls: type) -> ast.AST: if len(arg_nodes) == 1: slice_value = arg_nodes[0] else: - slice_value = ast.Tuple(elts=arg_nodes, ctx=ast.Load()) + slice_value = ast.Tuple(elts=arg_nodes, ctx=ast.Load()) # pyright: ignore [reportArgumentType] return ast.Subscript( - value=ast.Name(id=base_name), slice=ast.Index(value=slice_value), ctx=ast.Load() + value=ast.Name(id=base_name), + slice=ast.Index(value=slice_value), # pyright: ignore [reportArgumentType] + ctx=ast.Load(), ) @@ -575,7 +577,7 @@ def _generate_component_create_functiondef( arg=trigger, annotation=ast.Subscript( ast.Name("Optional"), - ast.Index( # type: ignore + ast.Index( # pyright: ignore [reportArgumentType] value=ast.Name( id=ast.unparse( figure_out_return_type( @@ -621,7 +623,7 @@ def _generate_component_create_functiondef( definition = ast.FunctionDef( name="create", args=create_args, - body=[ + body=[ # pyright: ignore [reportArgumentType] ast.Expr( value=ast.Constant( value=_generate_docstrings( @@ -630,7 +632,7 @@ def _generate_component_create_functiondef( ), ), ast.Expr( - value=ast.Ellipsis(), + value=ast.Constant(value=Ellipsis), ), ], decorator_list=[ @@ -641,7 +643,7 @@ def _generate_component_create_functiondef( else [ast.Name(id="classmethod")] ), ], - lineno=node.lineno if node is not None else None, + lineno=node.lineno if node is not None else None, # pyright: ignore [reportArgumentType] returns=ast.Constant(value=clz.__name__), ) return definition @@ -690,7 +692,7 @@ def _generate_staticmethod_call_functiondef( ), ], decorator_list=[ast.Name(id="staticmethod")], - lineno=node.lineno if node is not None else None, + lineno=node.lineno if node is not None else None, # pyright: ignore [reportArgumentType] returns=ast.Constant( value=_get_type_hint( typing.get_type_hints(clz.__call__).get("return", None), @@ -726,17 +728,17 @@ def _generate_namespace_call_functiondef( clz = classes[clz_name] if not hasattr(clz.__call__, "__self__"): - return _generate_staticmethod_call_functiondef(node, clz, type_hint_globals) # type: ignore + return _generate_staticmethod_call_functiondef(node, clz, type_hint_globals) # pyright: ignore [reportArgumentType] # Determine which class is wrapped by the namespace __call__ method component_clz = clz.__call__.__self__ - if clz.__call__.__func__.__name__ != "create": + if clz.__call__.__func__.__name__ != "create": # pyright: ignore [reportFunctionMemberAccess] return None definition = _generate_component_create_functiondef( node=None, - clz=component_clz, # type: ignore + clz=component_clz, # pyright: ignore [reportArgumentType] type_hint_globals=type_hint_globals, ) definition.name = "__call__" @@ -816,7 +818,7 @@ class StubGenerator(ast.NodeTransformer): The modified Module node. """ self.generic_visit(node) - return self._remove_docstring(node) # type: ignore + return self._remove_docstring(node) # pyright: ignore [reportReturnType] def visit_Import( self, node: ast.Import | ast.ImportFrom @@ -914,7 +916,7 @@ class StubGenerator(ast.NodeTransformer): node.body.append(call_definition) if not node.body: # We should never return an empty body. - node.body.append(ast.Expr(value=ast.Ellipsis())) + node.body.append(ast.Expr(value=ast.Constant(value=Ellipsis))) self.current_class = None return node @@ -941,9 +943,9 @@ class StubGenerator(ast.NodeTransformer): if node.name.startswith("_") and node.name != "__call__": return None # remove private methods - if node.body[-1] != ast.Expr(value=ast.Ellipsis()): + if node.body[-1] != ast.Expr(value=ast.Constant(value=Ellipsis)): # Blank out the function body for public functions. - node.body = [ast.Expr(value=ast.Ellipsis())] + node.body = [ast.Expr(value=ast.Constant(value=Ellipsis))] return node def visit_Assign(self, node: ast.Assign) -> ast.Assign | None: @@ -1077,7 +1079,7 @@ class PyiGenerator: + ( " # type: ignore" if mod in pyright_ignore_imports - else " # noqa" # ignore ruff formatting here for cases like rx.list. + else " # noqa: F401" # ignore ruff formatting here for cases like rx.list. if isinstance(mod, tuple) else "" ) diff --git a/reflex/utils/serializers.py b/reflex/utils/serializers.py index 4bb8dea92..f78438522 100644 --- a/reflex/utils/serializers.py +++ b/reflex/utils/serializers.py @@ -476,7 +476,7 @@ try: base64_image = base64.b64encode(image_bytes).decode("utf-8") try: # Newer method to get the mime type, but does not always work. - mime_type = image.get_format_mimetype() # type: ignore + mime_type = image.get_format_mimetype() # pyright: ignore [reportAttributeAccessIssue] except AttributeError: try: # Fallback method diff --git a/reflex/utils/types.py b/reflex/utils/types.py index 0b3ec7e9f..6257b1472 100644 --- a/reflex/utils/types.py +++ b/reflex/utils/types.py @@ -24,7 +24,7 @@ from typing import ( Tuple, Type, Union, - _GenericAlias, # type: ignore + _GenericAlias, # pyright: ignore [reportAttributeAccessIssue] get_args, get_type_hints, ) @@ -39,7 +39,9 @@ from reflex.components.core.breakpoints import Breakpoints try: from pydantic.v1.fields import ModelField except ModuleNotFoundError: - from pydantic.fields import ModelField # type: ignore + from pydantic.fields import ( + ModelField, # pyright: ignore [reportAttributeAccessIssue] + ) from sqlalchemy.ext.associationproxy import AssociationProxyInstance from sqlalchemy.ext.hybrid import hybrid_property @@ -70,13 +72,15 @@ GenericAliasTypes = [_GenericAlias] with contextlib.suppress(ImportError): # For newer versions of Python. - from types import GenericAlias # type: ignore + from types import GenericAlias GenericAliasTypes.append(GenericAlias) with contextlib.suppress(ImportError): # For older versions of Python. - from typing import _SpecialGenericAlias # type: ignore + from typing import ( + _SpecialGenericAlias, # pyright: ignore [reportAttributeAccessIssue] + ) GenericAliasTypes.append(_SpecialGenericAlias) @@ -175,7 +179,7 @@ def is_generic_alias(cls: GenericType) -> bool: Returns: Whether the class is a generic alias. """ - return isinstance(cls, GenericAliasTypes) + return isinstance(cls, GenericAliasTypes) # pyright: ignore [reportArgumentType] def unionize(*args: GenericType) -> Type: @@ -188,14 +192,14 @@ def unionize(*args: GenericType) -> Type: The unionized types. """ if not args: - return Any + return Any # pyright: ignore [reportReturnType] if len(args) == 1: return args[0] # We are bisecting the args list here to avoid hitting the recursion limit # In Python versions >= 3.11, we can simply do `return Union[*args]` midpoint = len(args) // 2 first_half, second_half = args[:midpoint], args[midpoint:] - return Union[unionize(*first_half), unionize(*second_half)] + return Union[unionize(*first_half), unionize(*second_half)] # pyright: ignore [reportReturnType] def is_none(cls: GenericType) -> bool: @@ -351,13 +355,13 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None if type_ is not None: if hasattr(column_type, "item_type"): try: - item_type = column_type.item_type.python_type # type: ignore + item_type = column_type.item_type.python_type # pyright: ignore [reportAttributeAccessIssue] except NotImplementedError: item_type = None if item_type is not None: if type_ in PrimitiveToAnnotation: - type_ = PrimitiveToAnnotation[type_] # type: ignore - type_ = type_[item_type] # type: ignore + type_ = PrimitiveToAnnotation[type_] + type_ = type_[item_type] # pyright: ignore [reportIndexIssue] if column.nullable: type_ = Optional[type_] return type_ @@ -432,7 +436,7 @@ def get_base_class(cls: GenericType) -> Type: return type(get_args(cls)[0]) if is_union(cls): - return tuple(get_base_class(arg) for arg in get_args(cls)) + return tuple(get_base_class(arg) for arg in get_args(cls)) # pyright: ignore [reportReturnType] return get_base_class(cls.__origin__) if is_generic_alias(cls) else cls diff --git a/reflex/vars/base.py b/reflex/vars/base.py index a3b3059e9..ac48355c4 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -662,7 +662,7 @@ class Var(Generic[VAR_TYPE]): return self.to(var_subclass.var_subclass, output) if fixed_output_type is None: - return get_to_operation(NoneVar).create(self) # type: ignore + return get_to_operation(NoneVar).create(self) # pyright: ignore [reportReturnType] # Handle fixed_output_type being Base or a dataclass. if can_use_in_object_var(fixed_output_type): @@ -679,7 +679,7 @@ class Var(Generic[VAR_TYPE]): to_operation_return = var_subclass.to_var_subclass.create( value=self, _var_type=new_var_type ) - return to_operation_return # type: ignore + return to_operation_return # pyright: ignore [reportReturnType] # If we can't determine the first argument, we just replace the _var_type. if not issubclass(output, Var) or var_type is None: @@ -1095,7 +1095,7 @@ class Var(Generic[VAR_TYPE]): The decoded value or the Var name. """ if isinstance(self, LiteralVar): - return self._var_value # type: ignore + return self._var_value try: return json.loads(str(self)) except ValueError: @@ -1222,7 +1222,7 @@ class ToOperation: """ return VarData.merge( self._original._get_all_var_data(), - self._var_data, # type: ignore + self._var_data, ) @classmethod @@ -1243,10 +1243,10 @@ class ToOperation: The ToOperation. """ return cls( - _js_expr="", # type: ignore - _var_data=_var_data, # type: ignore - _var_type=_var_type or cls._default_var_type, # type: ignore - _original=value, # type: ignore + _js_expr="", # pyright: ignore [reportCallIssue] + _var_data=_var_data, # pyright: ignore [reportCallIssue] + _var_type=_var_type or cls._default_var_type, # pyright: ignore [reportCallIssue, reportAttributeAccessIssue] + _original=value, # pyright: ignore [reportCallIssue] ) @@ -1435,7 +1435,7 @@ T = TypeVar("T") # NoReturn is used to match CustomVarOperationReturn with no type hint. @overload -def var_operation( +def var_operation( # pyright: ignore [reportOverlappingOverload] func: Callable[P, CustomVarOperationReturn[NoReturn]], ) -> Callable[P, Var]: ... @@ -1485,7 +1485,7 @@ def var_operation( ) -> Callable[P, Var[T]]: ... -def var_operation( +def var_operation( # pyright: ignore [reportInconsistentOverload] func: Callable[P, CustomVarOperationReturn[T]], ) -> Callable[P, Var[T]]: """Decorator for creating a var operation. @@ -1519,7 +1519,7 @@ def var_operation( return CustomVarOperation.create( name=func.__name__, args=tuple(list(args_vars.items()) + list(kwargs_vars.items())), - return_var=func(*args_vars.values(), **kwargs_vars), # type: ignore + return_var=func(*args_vars.values(), **kwargs_vars), # pyright: ignore [reportCallIssue, reportReturnType] ).guess_type() return wrapper @@ -1589,7 +1589,7 @@ class CachedVarOperation: next_class = parent_classes[parent_classes.index(CachedVarOperation) + 1] - return next_class.__getattr__(self, name) # type: ignore + return next_class.__getattr__(self, name) def _get_all_var_data(self) -> VarData | None: """Get all VarData associated with the Var. @@ -1611,7 +1611,7 @@ class CachedVarOperation: value._get_all_var_data() if isinstance(value, Var) else None for value in ( getattr(self, field.name) - for field in dataclasses.fields(self) # type: ignore + for field in dataclasses.fields(self) # pyright: ignore [reportArgumentType] ) ), self._var_data, @@ -1628,7 +1628,7 @@ class CachedVarOperation: type(self).__name__, *[ getattr(self, field.name) - for field in dataclasses.fields(self) # type: ignore + for field in dataclasses.fields(self) # pyright: ignore [reportArgumentType] if field.name not in ["_js_expr", "_var_data", "_var_type"] ], ) @@ -1645,7 +1645,7 @@ def and_operation(a: Var | Any, b: Var | Any) -> Var: Returns: The result of the logical AND operation. """ - return _and_operation(a, b) # type: ignore + return _and_operation(a, b) @var_operation @@ -1675,7 +1675,7 @@ def or_operation(a: Var | Any, b: Var | Any) -> Var: Returns: The result of the logical OR operation. """ - return _or_operation(a, b) # type: ignore + return _or_operation(a, b) @var_operation @@ -1804,7 +1804,7 @@ class ComputedVar(Var[RETURN_TYPE]): _fget: Callable[[BaseState], RETURN_TYPE] = dataclasses.field( default_factory=lambda: lambda _: None - ) # type: ignore + ) # pyright: ignore [reportAssignmentType] def __init__( self, @@ -2088,10 +2088,10 @@ class ComputedVar(Var[RETURN_TYPE]): return set() with contextlib.suppress(AttributeError): # unbox functools.partial - obj = cast(FunctionType, obj.func) # type: ignore + obj = cast(FunctionType, obj.func) # pyright: ignore [reportAttributeAccessIssue] with contextlib.suppress(AttributeError): # unbox EventHandler - obj = cast(FunctionType, obj.fn) # type: ignore + obj = cast(FunctionType, obj.fn) # pyright: ignore [reportAttributeAccessIssue] if self_name is None and isinstance(obj, FunctionType): try: @@ -2131,7 +2131,7 @@ class ComputedVar(Var[RETURN_TYPE]): d.update( self._deps( objclass=objclass, - obj=ref_obj, + obj=ref_obj, # pyright: ignore [reportArgumentType] ) ) # recurse into property fget functions @@ -2141,7 +2141,7 @@ class ComputedVar(Var[RETURN_TYPE]): d.update( self._deps( objclass=objclass, - obj=ref_obj.fget, # type: ignore + obj=ref_obj.fget, # pyright: ignore [reportArgumentType] ) ) elif ( @@ -2183,7 +2183,7 @@ class ComputedVar(Var[RETURN_TYPE]): hints = get_type_hints(self._fget) if "return" in hints: return hints["return"] - return Any + return Any # pyright: ignore [reportReturnType] @property def __class__(self) -> Type: @@ -2224,7 +2224,7 @@ def computed_var( interval: Optional[Union[datetime.timedelta, int]] = None, backend: bool | None = None, **kwargs, -) -> Callable[[Callable[[BASE_STATE], RETURN_TYPE]], ComputedVar[RETURN_TYPE]]: ... +) -> Callable[[Callable[[BASE_STATE], RETURN_TYPE]], ComputedVar[RETURN_TYPE]]: ... # pyright: ignore [reportInvalidTypeVarUse] @overload @@ -2553,7 +2553,7 @@ def get_uuid_string_var() -> Var: unique_uuid_var = get_unique_variable_name() unique_uuid_var_data = VarData( imports={ - f"$/{constants.Dirs.STATE_PATH}": {ImportVar(tag="generateUUID")}, # type: ignore + f"$/{constants.Dirs.STATE_PATH}": {ImportVar(tag="generateUUID")}, # pyright: ignore [reportArgumentType] "react": "useMemo", }, hooks={f"const {unique_uuid_var} = useMemo(generateUUID, [])": None}, @@ -2613,7 +2613,7 @@ def _extract_var_data(value: Iterable) -> list[VarData | None]: elif not isinstance(sub, str): # Recurse into dict values. if hasattr(sub, "values") and callable(sub.values): - var_datas.extend(_extract_var_data(sub.values())) + var_datas.extend(_extract_var_data(sub.values())) # pyright: ignore [reportArgumentType] # Recurse into iterable values (or dict keys). var_datas.extend(_extract_var_data(sub)) @@ -2624,7 +2624,7 @@ def _extract_var_data(value: Iterable) -> list[VarData | None]: # Recurse when value is a dict itself. values = getattr(value, "values", None) if callable(values): - var_datas.extend(_extract_var_data(values())) + var_datas.extend(_extract_var_data(values())) # pyright: ignore [reportArgumentType] return var_datas @@ -2932,7 +2932,7 @@ class Field(Generic[FIELD_TYPE]): @overload def __get__(self, instance, owner) -> FIELD_TYPE: ... - def __get__(self, instance, owner): # type: ignore + def __get__(self, instance, owner): # pyright: ignore [reportInconsistentOverload] """Get the Var. Args: @@ -2950,4 +2950,4 @@ def field(value: FIELD_TYPE) -> Field[FIELD_TYPE]: Returns: The Field. """ - return value # type: ignore + return value # pyright: ignore [reportReturnType] diff --git a/reflex/vars/datetime.py b/reflex/vars/datetime.py index b6f4c24c6..b20cfc7a6 100644 --- a/reflex/vars/datetime.py +++ b/reflex/vars/datetime.py @@ -40,7 +40,7 @@ class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)): def __lt__(self, other: datetime_types) -> BooleanVar: ... @overload - def __lt__(self, other: NoReturn) -> NoReturn: ... + def __lt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __lt__(self, other: Any): """Less than comparison. @@ -59,7 +59,7 @@ class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)): def __le__(self, other: datetime_types) -> BooleanVar: ... @overload - def __le__(self, other: NoReturn) -> NoReturn: ... + def __le__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __le__(self, other: Any): """Less than or equal comparison. @@ -78,7 +78,7 @@ class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)): def __gt__(self, other: datetime_types) -> BooleanVar: ... @overload - def __gt__(self, other: NoReturn) -> NoReturn: ... + def __gt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __gt__(self, other: Any): """Greater than comparison. @@ -97,7 +97,7 @@ class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)): def __ge__(self, other: datetime_types) -> BooleanVar: ... @overload - def __ge__(self, other: NoReturn) -> NoReturn: ... + def __ge__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __ge__(self, other: Any): """Greater than or equal comparison. diff --git a/reflex/vars/function.py b/reflex/vars/function.py index 131f15b9f..a82c4964b 100644 --- a/reflex/vars/function.py +++ b/reflex/vars/function.py @@ -100,7 +100,7 @@ class FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]): @overload def partial(self, *args: Var | Any) -> FunctionVar: ... - def partial(self, *args: Var | Any) -> FunctionVar: # type: ignore + def partial(self, *args: Var | Any) -> FunctionVar: # pyright: ignore [reportInconsistentOverload] """Partially apply the function with the given arguments. Args: @@ -174,7 +174,7 @@ class FunctionVar(Var[CALLABLE_TYPE], default_type=ReflexCallable[Any, Any]): @overload def call(self, *args: Var | Any) -> Var: ... - def call(self, *args: Var | Any) -> Var: # type: ignore + def call(self, *args: Var | Any) -> Var: # pyright: ignore [reportInconsistentOverload] """Call the function with the given arguments. Args: diff --git a/reflex/vars/number.py b/reflex/vars/number.py index 082334450..475c08b55 100644 --- a/reflex/vars/number.py +++ b/reflex/vars/number.py @@ -61,7 +61,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __add__(self, other: number_types) -> NumberVar: ... @overload - def __add__(self, other: NoReturn) -> NoReturn: ... + def __add__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __add__(self, other: Any): """Add two numbers. @@ -80,7 +80,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __radd__(self, other: number_types) -> NumberVar: ... @overload - def __radd__(self, other: NoReturn) -> NoReturn: ... + def __radd__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __radd__(self, other: Any): """Add two numbers. @@ -99,7 +99,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __sub__(self, other: number_types) -> NumberVar: ... @overload - def __sub__(self, other: NoReturn) -> NoReturn: ... + def __sub__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __sub__(self, other: Any): """Subtract two numbers. @@ -119,7 +119,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __rsub__(self, other: number_types) -> NumberVar: ... @overload - def __rsub__(self, other: NoReturn) -> NoReturn: ... + def __rsub__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __rsub__(self, other: Any): """Subtract two numbers. @@ -201,7 +201,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __truediv__(self, other: number_types) -> NumberVar: ... @overload - def __truediv__(self, other: NoReturn) -> NoReturn: ... + def __truediv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __truediv__(self, other: Any): """Divide two numbers. @@ -221,7 +221,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __rtruediv__(self, other: number_types) -> NumberVar: ... @overload - def __rtruediv__(self, other: NoReturn) -> NoReturn: ... + def __rtruediv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __rtruediv__(self, other: Any): """Divide two numbers. @@ -241,7 +241,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __floordiv__(self, other: number_types) -> NumberVar: ... @overload - def __floordiv__(self, other: NoReturn) -> NoReturn: ... + def __floordiv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __floordiv__(self, other: Any): """Floor divide two numbers. @@ -261,7 +261,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __rfloordiv__(self, other: number_types) -> NumberVar: ... @overload - def __rfloordiv__(self, other: NoReturn) -> NoReturn: ... + def __rfloordiv__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __rfloordiv__(self, other: Any): """Floor divide two numbers. @@ -281,7 +281,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __mod__(self, other: number_types) -> NumberVar: ... @overload - def __mod__(self, other: NoReturn) -> NoReturn: ... + def __mod__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __mod__(self, other: Any): """Modulo two numbers. @@ -301,7 +301,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __rmod__(self, other: number_types) -> NumberVar: ... @overload - def __rmod__(self, other: NoReturn) -> NoReturn: ... + def __rmod__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __rmod__(self, other: Any): """Modulo two numbers. @@ -321,7 +321,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __pow__(self, other: number_types) -> NumberVar: ... @overload - def __pow__(self, other: NoReturn) -> NoReturn: ... + def __pow__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __pow__(self, other: Any): """Exponentiate two numbers. @@ -341,7 +341,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __rpow__(self, other: number_types) -> NumberVar: ... @overload - def __rpow__(self, other: NoReturn) -> NoReturn: ... + def __rpow__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __rpow__(self, other: Any): """Exponentiate two numbers. @@ -417,7 +417,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __lt__(self, other: number_types) -> BooleanVar: ... @overload - def __lt__(self, other: NoReturn) -> NoReturn: ... + def __lt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __lt__(self, other: Any): """Less than comparison. @@ -436,7 +436,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __le__(self, other: number_types) -> BooleanVar: ... @overload - def __le__(self, other: NoReturn) -> NoReturn: ... + def __le__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __le__(self, other: Any): """Less than or equal comparison. @@ -481,7 +481,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __gt__(self, other: number_types) -> BooleanVar: ... @overload - def __gt__(self, other: NoReturn) -> NoReturn: ... + def __gt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __gt__(self, other: Any): """Greater than comparison. @@ -500,7 +500,7 @@ class NumberVar(Var[NUMBER_T], python_types=(int, float)): def __ge__(self, other: number_types) -> BooleanVar: ... @overload - def __ge__(self, other: NoReturn) -> NoReturn: ... + def __ge__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __ge__(self, other: Any): """Greater than or equal comparison. @@ -561,7 +561,7 @@ def binary_number_operation( Returns: The binary number operation. """ - return operation(lhs, rhs) # type: ignore + return operation(lhs, rhs) # pyright: ignore [reportReturnType, reportArgumentType] return wrapper diff --git a/reflex/vars/object.py b/reflex/vars/object.py index 7b951c559..fa8cdf8ec 100644 --- a/reflex/vars/object.py +++ b/reflex/vars/object.py @@ -75,9 +75,9 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=Mapping): """ fixed_type = get_origin(self._var_type) or self._var_type if not isclass(fixed_type): - return Any + return Any # pyright: ignore [reportReturnType] args = get_args(self._var_type) if issubclass(fixed_type, Mapping) else () - return args[1] if args else Any + return args[1] if args else Any # pyright: ignore [reportReturnType] def keys(self) -> ArrayVar[List[str]]: """Get the keys of the object. @@ -134,7 +134,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=Mapping): # NoReturn is used here to catch when key value is Any @overload - def __getitem__( + def __getitem__( # pyright: ignore [reportOverlappingOverload] self: ObjectVar[Mapping[Any, NoReturn]], key: Var | Any, ) -> Var: ... @@ -202,7 +202,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=Mapping): # NoReturn is used here to catch when key value is Any @overload - def __getattr__( + def __getattr__( # pyright: ignore [reportOverlappingOverload] self: ObjectVar[Mapping[Any, NoReturn]], name: str, ) -> Var: ... @@ -321,7 +321,7 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar): The type of the keys of the object. """ args_list = typing.get_args(self._var_type) - return args_list[0] if args_list else Any + return args_list[0] if args_list else Any # pyright: ignore [reportReturnType] def _value_type(self) -> Type: """Get the type of the values of the object. @@ -330,7 +330,7 @@ class LiteralObjectVar(CachedVarOperation, ObjectVar[OBJECT_TYPE], LiteralVar): The type of the values of the object. """ args_list = typing.get_args(self._var_type) - return args_list[1] if args_list else Any + return args_list[1] if args_list else Any # pyright: ignore [reportReturnType] @cached_property_no_lock def _cached_var_name(self) -> str: diff --git a/reflex/vars/sequence.py b/reflex/vars/sequence.py index 1b11f50e6..fa1ab5bf3 100644 --- a/reflex/vars/sequence.py +++ b/reflex/vars/sequence.py @@ -66,7 +66,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def __add__(self, other: StringVar | str) -> ConcatVarOperation: ... @overload - def __add__(self, other: NoReturn) -> NoReturn: ... + def __add__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __add__(self, other: Any) -> ConcatVarOperation: """Concatenate two strings. @@ -86,7 +86,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def __radd__(self, other: StringVar | str) -> ConcatVarOperation: ... @overload - def __radd__(self, other: NoReturn) -> NoReturn: ... + def __radd__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __radd__(self, other: Any) -> ConcatVarOperation: """Concatenate two strings. @@ -106,7 +106,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def __mul__(self, other: NumberVar | int) -> StringVar: ... @overload - def __mul__(self, other: NoReturn) -> NoReturn: ... + def __mul__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __mul__(self, other: Any) -> StringVar: """Multiply the sequence by a number or an integer. @@ -126,7 +126,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def __rmul__(self, other: NumberVar | int) -> StringVar: ... @overload - def __rmul__(self, other: NoReturn) -> NoReturn: ... + def __rmul__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __rmul__(self, other: Any) -> StringVar: """Multiply the sequence by a number or an integer. @@ -211,7 +211,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): ) -> BooleanVar: ... @overload - def contains( + def contains( # pyright: ignore [reportOverlappingOverload] self, other: NoReturn, field: StringVar | str | None = None ) -> NoReturn: ... @@ -237,7 +237,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def split(self, separator: StringVar | str = "") -> ArrayVar[List[str]]: ... @overload - def split(self, separator: NoReturn) -> NoReturn: ... + def split(self, separator: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def split(self, separator: Any = "") -> ArrayVar[List[str]]: """Split the string. @@ -256,7 +256,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def startswith(self, prefix: StringVar | str) -> BooleanVar: ... @overload - def startswith(self, prefix: NoReturn) -> NoReturn: ... + def startswith(self, prefix: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def startswith(self, prefix: Any) -> BooleanVar: """Check if the string starts with a prefix. @@ -275,7 +275,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def endswith(self, suffix: StringVar | str) -> BooleanVar: ... @overload - def endswith(self, suffix: NoReturn) -> NoReturn: ... + def endswith(self, suffix: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def endswith(self, suffix: Any) -> BooleanVar: """Check if the string ends with a suffix. @@ -294,7 +294,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def __lt__(self, other: StringVar | str) -> BooleanVar: ... @overload - def __lt__(self, other: NoReturn) -> NoReturn: ... + def __lt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __lt__(self, other: Any): """Check if the string is less than another string. @@ -314,7 +314,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def __gt__(self, other: StringVar | str) -> BooleanVar: ... @overload - def __gt__(self, other: NoReturn) -> NoReturn: ... + def __gt__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __gt__(self, other: Any): """Check if the string is greater than another string. @@ -334,7 +334,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def __le__(self, other: StringVar | str) -> BooleanVar: ... @overload - def __le__(self, other: NoReturn) -> NoReturn: ... + def __le__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __le__(self, other: Any): """Check if the string is less than or equal to another string. @@ -354,7 +354,7 @@ class StringVar(Var[STRING_TYPE], python_types=str): def __ge__(self, other: StringVar | str) -> BooleanVar: ... @overload - def __ge__(self, other: NoReturn) -> NoReturn: ... + def __ge__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __ge__(self, other: Any): """Check if the string is greater than or equal to another string. @@ -811,7 +811,7 @@ class ArrayVar(Var[ARRAY_VAR_TYPE], python_types=(list, tuple, set)): def join(self, sep: StringVar | str = "") -> StringVar: ... @overload - def join(self, sep: NoReturn) -> NoReturn: ... + def join(self, sep: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def join(self, sep: Any = "") -> StringVar: """Join the elements of the array. @@ -858,7 +858,7 @@ class ArrayVar(Var[ARRAY_VAR_TYPE], python_types=(list, tuple, set)): def __add__(self, other: ArrayVar[ARRAY_VAR_TYPE]) -> ArrayVar[ARRAY_VAR_TYPE]: ... @overload - def __add__(self, other: NoReturn) -> NoReturn: ... + def __add__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __add__(self, other: Any) -> ArrayVar[ARRAY_VAR_TYPE]: """Concatenate two arrays. @@ -1089,7 +1089,7 @@ class ArrayVar(Var[ARRAY_VAR_TYPE], python_types=(list, tuple, set)): def __mul__(self, other: NumberVar | int) -> ArrayVar[ARRAY_VAR_TYPE]: ... @overload - def __mul__(self, other: NoReturn) -> NoReturn: ... + def __mul__(self, other: NoReturn) -> NoReturn: ... # pyright: ignore [reportOverlappingOverload] def __mul__(self, other: Any) -> ArrayVar[ARRAY_VAR_TYPE]: """Multiply the sequence by a number or integer. @@ -1107,7 +1107,7 @@ class ArrayVar(Var[ARRAY_VAR_TYPE], python_types=(list, tuple, set)): return repeat_array_operation(self, other) - __rmul__ = __mul__ # type: ignore + __rmul__ = __mul__ @overload def __lt__(self, other: ArrayVar[ARRAY_VAR_TYPE]) -> BooleanVar: ... @@ -1691,7 +1691,7 @@ def array_concat_operation( """ return var_operation_return( js_expression=f"[...{lhs}, ...{rhs}]", - var_type=Union[lhs._var_type, rhs._var_type], + var_type=Union[lhs._var_type, rhs._var_type], # pyright: ignore [reportArgumentType] ) diff --git a/tests/integration/test_background_task.py b/tests/integration/test_background_task.py index cb8fda019..f312f8122 100644 --- a/tests/integration/test_background_task.py +++ b/tests/integration/test_background_task.py @@ -37,9 +37,9 @@ def BackgroundTask(): self._task_id += 1 for ix in range(int(self.iterations)): if ix % 2 == 0: - yield State.increment_arbitrary(1) # type: ignore + yield State.increment_arbitrary(1) else: - yield State.increment() # type: ignore + yield State.increment() await asyncio.sleep(0.005) @rx.event @@ -125,8 +125,8 @@ def BackgroundTask(): rx.input( id="iterations", placeholder="Iterations", - value=State.iterations.to_string(), # type: ignore - on_change=State.set_iterations, # type: ignore + value=State.iterations.to_string(), # pyright: ignore [reportAttributeAccessIssue] + on_change=State.set_iterations, # pyright: ignore [reportAttributeAccessIssue] ), rx.button( "Delayed Increment", @@ -288,7 +288,7 @@ def test_background_task( assert background_task._poll_for(lambda: counter.text == "620", timeout=40) # all tasks should have exited and cleaned up assert background_task._poll_for( - lambda: not background_task.app_instance._background_tasks # type: ignore + lambda: not background_task.app_instance._background_tasks # pyright: ignore [reportOptionalMemberAccess] ) diff --git a/tests/integration/test_component_state.py b/tests/integration/test_component_state.py index 381c1d23a..654dc7ce9 100644 --- a/tests/integration/test_component_state.py +++ b/tests/integration/test_component_state.py @@ -30,7 +30,7 @@ def ComponentStateApp(): @rx.event def increment(self): self.count += 1 - self._be = self.count # type: ignore + self._be = self.count # pyright: ignore [reportAttributeAccessIssue] @classmethod def get_component(cls, *children, **props): @@ -72,7 +72,7 @@ def ComponentStateApp(): State=_Counter, ) - app = rx.App(_state=rx.State) # noqa + app = rx.App(_state=rx.State) # noqa: F841 @rx.page() def index(): @@ -89,7 +89,7 @@ def ComponentStateApp(): mc_d, rx.button( "Inc A", - on_click=mc_a.State.increment, # type: ignore + on_click=mc_a.State.increment, # pyright: ignore [reportAttributeAccessIssue, reportOptionalMemberAccess] id="inc-a", ), rx.text( diff --git a/tests/integration/test_connection_banner.py b/tests/integration/test_connection_banner.py index c2a912af6..c80f30626 100644 --- a/tests/integration/test_connection_banner.py +++ b/tests/integration/test_connection_banner.py @@ -31,7 +31,7 @@ def ConnectionBanner(): rx.button( "Increment", id="increment", - on_click=State.set_foo(State.foo + 1), # type: ignore + on_click=State.set_foo(State.foo + 1), # pyright: ignore [reportAttributeAccessIssue] ), rx.button("Delay", id="delay", on_click=State.delay), ) diff --git a/tests/integration/test_deploy_url.py b/tests/integration/test_deploy_url.py index 8b5776260..207f37609 100644 --- a/tests/integration/test_deploy_url.py +++ b/tests/integration/test_deploy_url.py @@ -19,7 +19,7 @@ def DeployUrlSample() -> None: class State(rx.State): @rx.event def goto_self(self): - return rx.redirect(rx.config.get_config().deploy_url) # type: ignore + return rx.redirect(rx.config.get_config().deploy_url) # pyright: ignore [reportArgumentType] def index(): return rx.fragment( diff --git a/tests/integration/test_dynamic_routes.py b/tests/integration/test_dynamic_routes.py index 9032fd84c..40886a601 100644 --- a/tests/integration/test_dynamic_routes.py +++ b/tests/integration/test_dynamic_routes.py @@ -49,7 +49,7 @@ def DynamicRoute(): read_only=True, id="token", ), - rx.input(value=rx.State.page_id, read_only=True, id="page_id"), # type: ignore + rx.input(value=rx.State.page_id, read_only=True, id="page_id"), # pyright: ignore [reportAttributeAccessIssue] rx.input( value=DynamicState.router.page.raw_path, read_only=True, @@ -60,12 +60,12 @@ def DynamicRoute(): rx.link( "next", href="/page/" + DynamicState.next_page, - id="link_page_next", # type: ignore + id="link_page_next", ), rx.link("missing", href="/missing", id="link_missing"), - rx.list( # type: ignore + rx.list( # pyright: ignore [reportAttributeAccessIssue] rx.foreach( - DynamicState.order, # type: ignore + DynamicState.order, # pyright: ignore [reportAttributeAccessIssue] lambda i: rx.list_item(rx.text(i)), ), ), @@ -98,11 +98,11 @@ def DynamicRoute(): rx.data_list.root( rx.data_list.item( rx.data_list.label("rx.State.arg_str (dynamic)"), - rx.data_list.value(rx.State.arg_str, id="state-arg_str"), # type: ignore + rx.data_list.value(rx.State.arg_str, id="state-arg_str"), # pyright: ignore [reportAttributeAccessIssue] ), rx.data_list.item( rx.data_list.label("ArgState.arg_str (dynamic) (inherited)"), - rx.data_list.value(ArgState.arg_str, id="argstate-arg_str"), # type: ignore + rx.data_list.value(ArgState.arg_str, id="argstate-arg_str"), # pyright: ignore [reportAttributeAccessIssue] ), rx.data_list.item( rx.data_list.label("ArgState.arg"), @@ -110,7 +110,7 @@ def DynamicRoute(): ), rx.data_list.item( rx.data_list.label("ArgSubState.arg_str (dynamic) (inherited)"), - rx.data_list.value(ArgSubState.arg_str, id="argsubstate-arg_str"), # type: ignore + rx.data_list.value(ArgSubState.arg_str, id="argsubstate-arg_str"), # pyright: ignore [reportAttributeAccessIssue] ), rx.data_list.item( rx.data_list.label("ArgSubState.arg (inherited)"), @@ -134,15 +134,15 @@ def DynamicRoute(): height="100vh", ) - @rx.page(route="/redirect-page/[page_id]", on_load=DynamicState.on_load_redir) # type: ignore + @rx.page(route="/redirect-page/[page_id]", on_load=DynamicState.on_load_redir) def redirect_page(): return rx.fragment(rx.text("redirecting...")) app = rx.App(_state=rx.State) - app.add_page(index, route="/page/[page_id]", on_load=DynamicState.on_load) # type: ignore - app.add_page(index, route="/static/x", on_load=DynamicState.on_load) # type: ignore + app.add_page(index, route="/page/[page_id]", on_load=DynamicState.on_load) + app.add_page(index, route="/static/x", on_load=DynamicState.on_load) app.add_page(index) - app.add_custom_404_page(on_load=DynamicState.on_load) # type: ignore + app.add_custom_404_page(on_load=DynamicState.on_load) @pytest.fixture(scope="module") diff --git a/tests/integration/test_event_actions.py b/tests/integration/test_event_actions.py index cc8e97b09..707410075 100644 --- a/tests/integration/test_event_actions.py +++ b/tests/integration/test_event_actions.py @@ -63,16 +63,16 @@ def TestEventAction(): rx.button( "Stop Prop Only", id="btn-stop-prop-only", - on_click=rx.stop_propagation, # type: ignore + on_click=rx.stop_propagation, # pyright: ignore [reportArgumentType] ), rx.button( "Click event", - on_click=EventActionState.on_click("no_event_actions"), # type: ignore + on_click=EventActionState.on_click("no_event_actions"), # pyright: ignore [reportCallIssue] id="btn-click-event", ), rx.button( "Click stop propagation", - on_click=EventActionState.on_click("stop_propagation").stop_propagation, # type: ignore + on_click=EventActionState.on_click("stop_propagation").stop_propagation, # pyright: ignore [reportCallIssue] id="btn-click-stop-propagation", ), rx.button( @@ -88,13 +88,13 @@ def TestEventAction(): rx.link( "Link", href="#", - on_click=EventActionState.on_click("link_no_event_actions"), # type: ignore + on_click=EventActionState.on_click("link_no_event_actions"), # pyright: ignore [reportCallIssue] id="link", ), rx.link( "Link Stop Propagation", href="#", - on_click=EventActionState.on_click( # type: ignore + on_click=EventActionState.on_click( # pyright: ignore [reportCallIssue] "link_stop_propagation" ).stop_propagation, id="link-stop-propagation", @@ -102,13 +102,13 @@ def TestEventAction(): rx.link( "Link Prevent Default Only", href="/invalid", - on_click=rx.prevent_default, # type: ignore + on_click=rx.prevent_default, # pyright: ignore [reportArgumentType] id="link-prevent-default-only", ), rx.link( "Link Prevent Default", href="/invalid", - on_click=EventActionState.on_click( # type: ignore + on_click=EventActionState.on_click( # pyright: ignore [reportCallIssue] "link_prevent_default" ).prevent_default, id="link-prevent-default", @@ -116,44 +116,44 @@ def TestEventAction(): rx.link( "Link Both", href="/invalid", - on_click=EventActionState.on_click( # type: ignore + on_click=EventActionState.on_click( # pyright: ignore [reportCallIssue] "link_both" ).stop_propagation.prevent_default, id="link-stop-propagation-prevent-default", ), EventFiringComponent.create( id="custom-stop-propagation", - on_click=EventActionState.on_click( # type: ignore + on_click=EventActionState.on_click( # pyright: ignore [reportCallIssue] "custom-stop-propagation" ).stop_propagation, ), EventFiringComponent.create( id="custom-prevent-default", - on_click=EventActionState.on_click( # type: ignore + on_click=EventActionState.on_click( # pyright: ignore [reportCallIssue] "custom-prevent-default" ).prevent_default, ), rx.button( "Throttle", id="btn-throttle", - on_click=lambda: EventActionState.on_click_throttle.throttle( + on_click=lambda: EventActionState.on_click_throttle.throttle( # pyright: ignore [reportFunctionMemberAccess] 200 ).stop_propagation, ), rx.button( "Debounce", id="btn-debounce", - on_click=EventActionState.on_click_debounce.debounce( + on_click=EventActionState.on_click_debounce.debounce( # pyright: ignore [reportFunctionMemberAccess] 200 ).stop_propagation, ), - rx.list( # type: ignore + rx.list( # pyright: ignore [reportAttributeAccessIssue] rx.foreach( - EventActionState.order, # type: ignore + EventActionState.order, rx.list_item, ), ), - on_click=EventActionState.on_click("outer"), # type: ignore + on_click=EventActionState.on_click("outer"), # pyright: ignore [reportCallIssue] ) app = rx.App(_state=rx.State) diff --git a/tests/integration/test_event_chain.py b/tests/integration/test_event_chain.py index 5a933253a..df571e884 100644 --- a/tests/integration/test_event_chain.py +++ b/tests/integration/test_event_chain.py @@ -43,32 +43,32 @@ def EventChain(): def event_nested_1(self): self.event_order.append("event_nested_1") yield State.event_nested_2 - yield State.event_arg("nested_1") # type: ignore + yield State.event_arg("nested_1") @rx.event def event_nested_2(self): self.event_order.append("event_nested_2") yield State.event_nested_3 yield rx.console_log("event_nested_2") - yield State.event_arg("nested_2") # type: ignore + yield State.event_arg("nested_2") @rx.event def event_nested_3(self): self.event_order.append("event_nested_3") yield State.event_no_args - yield State.event_arg("nested_3") # type: ignore + yield State.event_arg("nested_3") @rx.event def on_load_return_chain(self): self.event_order.append("on_load_return_chain") - return [State.event_arg(1), State.event_arg(2), State.event_arg(3)] # type: ignore + return [State.event_arg(1), State.event_arg(2), State.event_arg(3)] @rx.event def on_load_yield_chain(self): self.event_order.append("on_load_yield_chain") - yield State.event_arg(4) # type: ignore - yield State.event_arg(5) # type: ignore - yield State.event_arg(6) # type: ignore + yield State.event_arg(4) + yield State.event_arg(5) + yield State.event_arg(6) @rx.event def click_return_event(self): @@ -79,28 +79,28 @@ def EventChain(): def click_return_events(self): self.event_order.append("click_return_events") return [ - State.event_arg(7), # type: ignore + State.event_arg(7), rx.console_log("click_return_events"), - State.event_arg(8), # type: ignore - State.event_arg(9), # type: ignore + State.event_arg(8), + State.event_arg(9), ] @rx.event def click_yield_chain(self): self.event_order.append("click_yield_chain:0") - yield State.event_arg(10) # type: ignore + yield State.event_arg(10) self.event_order.append("click_yield_chain:1") yield rx.console_log("click_yield_chain") - yield State.event_arg(11) # type: ignore + yield State.event_arg(11) self.event_order.append("click_yield_chain:2") - yield State.event_arg(12) # type: ignore + yield State.event_arg(12) self.event_order.append("click_yield_chain:3") @rx.event def click_yield_many_events(self): self.event_order.append("click_yield_many_events") for ix in range(MANY_EVENTS): - yield State.event_arg(ix) # type: ignore + yield State.event_arg(ix) yield rx.console_log(f"many_events_{ix}") self.event_order.append("click_yield_many_events_done") @@ -108,7 +108,7 @@ def EventChain(): def click_yield_nested(self): self.event_order.append("click_yield_nested") yield State.event_nested_1 - yield State.event_arg("yield_nested") # type: ignore + yield State.event_arg("yield_nested") @rx.event def redirect_return_chain(self): @@ -123,12 +123,12 @@ def EventChain(): @rx.event def click_return_int_type(self): self.event_order.append("click_return_int_type") - return State.event_arg_repr_type(1) # type: ignore + return State.event_arg_repr_type(1) @rx.event def click_return_dict_type(self): self.event_order.append("click_return_dict_type") - return State.event_arg_repr_type({"a": 1}) # type: ignore + return State.event_arg_repr_type({"a": 1}) @rx.event async def click_yield_interim_value_async(self): @@ -193,12 +193,12 @@ def EventChain(): rx.button( "Click Int Type", id="click_int_type", - on_click=lambda: State.event_arg_repr_type(1), # type: ignore + on_click=lambda: State.event_arg_repr_type(1), ), rx.button( "Click Dict Type", id="click_dict_type", - on_click=lambda: State.event_arg_repr_type({"a": 1}), # type: ignore + on_click=lambda: State.event_arg_repr_type({"a": 1}), ), rx.button( "Return Chain Int Type", @@ -239,7 +239,7 @@ def EventChain(): rx.text( "return", on_mount=State.on_load_return_chain, - on_unmount=lambda: State.event_arg("unmount"), # type: ignore + on_unmount=lambda: State.event_arg("unmount"), ), token_input, rx.button("Unmount", on_click=rx.redirect("/"), id="unmount"), @@ -251,7 +251,7 @@ def EventChain(): "yield", on_mount=[ State.on_load_yield_chain, - lambda: State.event_arg("mount"), # type: ignore + lambda: State.event_arg("mount"), ], on_unmount=State.event_no_args, ), @@ -259,8 +259,8 @@ def EventChain(): rx.button("Unmount", on_click=rx.redirect("/"), id="unmount"), ) - app.add_page(on_load_return_chain, on_load=State.on_load_return_chain) # type: ignore - app.add_page(on_load_yield_chain, on_load=State.on_load_yield_chain) # type: ignore + app.add_page(on_load_return_chain, on_load=State.on_load_return_chain) + app.add_page(on_load_yield_chain, on_load=State.on_load_yield_chain) app.add_page(on_mount_return_chain) app.add_page(on_mount_yield_chain) diff --git a/tests/integration/test_exception_handlers.py b/tests/integration/test_exception_handlers.py index 4d15bbf01..71858b899 100644 --- a/tests/integration/test_exception_handlers.py +++ b/tests/integration/test_exception_handlers.py @@ -51,12 +51,12 @@ def TestApp(): ), rx.button( "induce_backend_error", - on_click=lambda: TestAppState.divide_by_number(0), # type: ignore + on_click=lambda: TestAppState.divide_by_number(0), # pyright: ignore [reportCallIssue] id="induce-backend-error-btn", ), rx.button( "induce_react_error", - on_click=TestAppState.set_react_error(True), # type: ignore + on_click=TestAppState.set_react_error(True), # pyright: ignore [reportAttributeAccessIssue] id="induce-react-error-btn", ), rx.box( diff --git a/tests/integration/test_input.py b/tests/integration/test_input.py index bddeca45f..5f2948feb 100644 --- a/tests/integration/test_input.py +++ b/tests/integration/test_input.py @@ -26,11 +26,11 @@ def FullyControlledInput(): ), rx.input( id="debounce_input_input", - on_change=State.set_text, # type: ignore + on_change=State.set_text, # pyright: ignore [reportAttributeAccessIssue] value=State.text, ), rx.input(value=State.text, id="value_input", is_read_only=True), - rx.input(on_change=State.set_text, id="on_change_input"), # type: ignore + rx.input(on_change=State.set_text, id="on_change_input"), # pyright: ignore [reportAttributeAccessIssue] rx.el.input( value=State.text, id="plain_value_input", diff --git a/tests/integration/test_lifespan.py b/tests/integration/test_lifespan.py index d79273fbc..24dd7df6a 100644 --- a/tests/integration/test_lifespan.py +++ b/tests/integration/test_lifespan.py @@ -65,7 +65,7 @@ def LifespanApp(): rx.moment( interval=LifespanState.interval, on_change=LifespanState.tick ), - on_click=LifespanState.set_interval( # type: ignore + on_click=LifespanState.set_interval( # pyright: ignore [reportAttributeAccessIssue] rx.cond(LifespanState.interval, 0, 100) ), id="toggle-tick", @@ -113,13 +113,13 @@ async def test_lifespan(lifespan_app: AppHarness): task_global = driver.find_element(By.ID, "task_global") assert context_global.text == "2" - assert lifespan_app.app_module.lifespan_context_global == 2 # type: ignore + assert lifespan_app.app_module.lifespan_context_global == 2 original_task_global_text = task_global.text original_task_global_value = int(original_task_global_text) lifespan_app.poll_for_content(task_global, exp_not_equal=original_task_global_text) driver.find_element(By.ID, "toggle-tick").click() # avoid teardown errors - assert lifespan_app.app_module.lifespan_task_global > original_task_global_value # type: ignore + assert lifespan_app.app_module.lifespan_task_global > original_task_global_value assert int(task_global.text) > original_task_global_value # Kill the backend diff --git a/tests/integration/test_login_flow.py b/tests/integration/test_login_flow.py index 7eb46ab39..a1df015bf 100644 --- a/tests/integration/test_login_flow.py +++ b/tests/integration/test_login_flow.py @@ -31,8 +31,8 @@ def LoginSample(): yield rx.redirect("/") def index(): - return rx.cond( - State.is_hydrated & State.auth_token, # type: ignore + return rx.cond( # pyright: ignore [reportCallIssue] + State.is_hydrated & State.auth_token, # pyright: ignore [reportOperatorIssue] rx.vstack( rx.heading(State.auth_token, id="auth-token"), rx.button("Logout", on_click=State.logout, id="logout"), diff --git a/tests/integration/test_media.py b/tests/integration/test_media.py index 649038a7e..f3ce65c87 100644 --- a/tests/integration/test_media.py +++ b/tests/integration/test_media.py @@ -19,7 +19,7 @@ def MediaApp(): def _blue(self, format=None) -> Image.Image: img = Image.new("RGB", (200, 200), "blue") if format is not None: - img.format = format # type: ignore + img.format = format return img @rx.var @@ -50,7 +50,7 @@ def MediaApp(): def img_from_url(self) -> Image.Image: img_url = "https://picsum.photos/id/1/200/300" img_resp = httpx.get(img_url, follow_redirects=True) - return Image.open(img_resp) # type: ignore + return Image.open(img_resp) # pyright: ignore [reportArgumentType] app = rx.App() diff --git a/tests/integration/test_state_inheritance.py b/tests/integration/test_state_inheritance.py index 6b93a2ed7..f544fcc92 100644 --- a/tests/integration/test_state_inheritance.py +++ b/tests/integration/test_state_inheritance.py @@ -131,7 +131,7 @@ def StateInheritance(): rx.heading(Base1.child_mixin, id="base1-child-mixin"), rx.button( "Base1.on_click_mixin", - on_click=Base1.on_click_mixin, # type: ignore + on_click=Base1.on_click_mixin, id="base1-mixin-btn", ), rx.heading( @@ -153,7 +153,7 @@ def StateInheritance(): rx.heading(Child1.child_mixin, id="child1-child-mixin"), rx.button( "Child1.on_click_other_mixin", - on_click=Child1.on_click_other_mixin, # type: ignore + on_click=Child1.on_click_other_mixin, id="child1-other-mixin-btn", ), # Child 2 (Mixin, ChildMixin, OtherMixin) @@ -166,12 +166,12 @@ def StateInheritance(): rx.heading(Child2.child_mixin, id="child2-child-mixin"), rx.button( "Child2.on_click_mixin", - on_click=Child2.on_click_mixin, # type: ignore + on_click=Child2.on_click_mixin, id="child2-mixin-btn", ), rx.button( "Child2.on_click_other_mixin", - on_click=Child2.on_click_other_mixin, # type: ignore + on_click=Child2.on_click_other_mixin, id="child2-other-mixin-btn", ), # Child 3 (Mixin, ChildMixin, OtherMixin) @@ -186,12 +186,12 @@ def StateInheritance(): rx.heading(Child3.child_mixin, id="child3-child-mixin"), rx.button( "Child3.on_click_mixin", - on_click=Child3.on_click_mixin, # type: ignore + on_click=Child3.on_click_mixin, id="child3-mixin-btn", ), rx.button( "Child3.on_click_other_mixin", - on_click=Child3.on_click_other_mixin, # type: ignore + on_click=Child3.on_click_other_mixin, id="child3-other-mixin-btn", ), rx.heading( diff --git a/tests/integration/test_upload.py b/tests/integration/test_upload.py index 07c3997b4..a0df05f52 100644 --- a/tests/integration/test_upload.py +++ b/tests/integration/test_upload.py @@ -80,7 +80,7 @@ def UploadFile(): ), rx.button( "Upload", - on_click=lambda: UploadState.handle_upload(rx.upload_files()), # type: ignore + on_click=lambda: UploadState.handle_upload(rx.upload_files()), # pyright: ignore [reportCallIssue] id="upload_button", ), rx.box( @@ -105,7 +105,7 @@ def UploadFile(): ), rx.button( "Upload", - on_click=UploadState.handle_upload_secondary( # type: ignore + on_click=UploadState.handle_upload_secondary( # pyright: ignore [reportCallIssue] rx.upload_files( upload_id="secondary", on_upload_progress=UploadState.upload_progress, @@ -127,7 +127,7 @@ def UploadFile(): ), rx.vstack( rx.foreach( - UploadState.progress_dicts, # type: ignore + UploadState.progress_dicts, lambda d: rx.text(d.to_string()), ) ), @@ -146,7 +146,7 @@ def UploadFile(): ), rx.button( "Upload", - on_click=UploadState.handle_upload_tertiary( # type: ignore + on_click=UploadState.handle_upload_tertiary( # pyright: ignore [reportCallIssue] rx.upload_files( upload_id="tertiary", ), diff --git a/tests/integration/test_var_operations.py b/tests/integration/test_var_operations.py index 86d68340a..a09c8612e 100644 --- a/tests/integration/test_var_operations.py +++ b/tests/integration/test_var_operations.py @@ -7,42 +7,38 @@ from selenium.webdriver.common.by import By from reflex.testing import AppHarness -# pyright: reportOptionalMemberAccess=false, reportGeneralTypeIssues=false, reportUnknownMemberType=false - def VarOperations(): """App with var operations.""" - from typing import Dict, List - import reflex as rx from reflex.vars.base import LiteralVar from reflex.vars.sequence import ArrayVar class Object(rx.Base): - str: str = "hello" + name: str = "hello" class VarOperationState(rx.State): - int_var1: int = 10 - int_var2: int = 5 - int_var3: int = 7 - float_var1: float = 10.5 - float_var2: float = 5.5 - list1: List = [1, 2] - list2: List = [3, 4] - list3: List = ["first", "second", "third"] - list4: List = [Object(name="obj_1"), Object(name="obj_2")] - str_var1: str = "first" - str_var2: str = "second" - str_var3: str = "ThIrD" - str_var4: str = "a long string" - dict1: Dict[int, int] = {1: 2} - dict2: Dict[int, int] = {3: 4} - html_str: str = "
hello
" + int_var1: rx.Field[int] = rx.field(10) + int_var2: rx.Field[int] = rx.field(5) + int_var3: rx.Field[int] = rx.field(7) + float_var1: rx.Field[float] = rx.field(10.5) + float_var2: rx.Field[float] = rx.field(5.5) + list1: rx.Field[list] = rx.field([1, 2]) + list2: rx.Field[list] = rx.field([3, 4]) + list3: rx.Field[list] = rx.field(["first", "second", "third"]) + list4: rx.Field[list] = rx.field([Object(name="obj_1"), Object(name="obj_2")]) + str_var1: rx.Field[str] = rx.field("first") + str_var2: rx.Field[str] = rx.field("second") + str_var3: rx.Field[str] = rx.field("ThIrD") + str_var4: rx.Field[str] = rx.field("a long string") + dict1: rx.Field[dict[int, int]] = rx.field({1: 2}) + dict2: rx.Field[dict[int, int]] = rx.field({3: 4}) + html_str: rx.Field[str] = rx.field("
hello
") app = rx.App(_state=rx.State) @rx.memo - def memo_comp(list1: List[int], int_var1: int, id: str): + def memo_comp(list1: list[int], int_var1: int, id: str): return rx.text(list1, int_var1, id=id) @rx.memo @@ -378,7 +374,8 @@ def VarOperations(): id="str_contains", ), rx.text( - VarOperationState.str_var1 | VarOperationState.str_var1, id="str_or_str" + VarOperationState.str_var1 | VarOperationState.str_var1, + id="str_or_str", ), rx.text( VarOperationState.str_var1 & VarOperationState.str_var2, @@ -394,7 +391,8 @@ def VarOperations(): id="str_and_int", ), rx.text( - VarOperationState.str_var1 | VarOperationState.int_var2, id="str_or_int" + VarOperationState.str_var1 | VarOperationState.int_var2, + id="str_or_int", ), rx.text( (VarOperationState.str_var1 == VarOperationState.int_var1).to_string(), @@ -406,7 +404,8 @@ def VarOperations(): ), # STR, LIST rx.text( - VarOperationState.str_var1 | VarOperationState.list1, id="str_or_list" + VarOperationState.str_var1 | VarOperationState.list1, + id="str_or_list", ), rx.text( (VarOperationState.str_var1 & VarOperationState.list1).to_string(), @@ -422,7 +421,8 @@ def VarOperations(): ), # STR, DICT rx.text( - VarOperationState.str_var1 | VarOperationState.dict1, id="str_or_dict" + VarOperationState.str_var1 | VarOperationState.dict1, + id="str_or_dict", ), rx.text( (VarOperationState.str_var1 & VarOperationState.dict1).to_string(), @@ -474,7 +474,8 @@ def VarOperations(): id="list_neq_list", ), rx.text( - VarOperationState.list1.contains(1).to_string(), id="list_contains" + VarOperationState.list1.contains(1).to_string(), + id="list_contains", ), rx.text(VarOperationState.list4.pluck("name").to_string(), id="list_pluck"), rx.text(VarOperationState.list1.reverse().to_string(), id="list_reverse"), @@ -534,7 +535,8 @@ def VarOperations(): id="dict_neq_dict", ), rx.text( - VarOperationState.dict1.contains(1).to_string(), id="dict_contains" + VarOperationState.dict1.contains(1).to_string(), + id="dict_contains", ), rx.text(VarOperationState.str_var3.lower(), id="str_lower"), rx.text(VarOperationState.str_var3.upper(), id="str_upper"), @@ -571,7 +573,7 @@ def VarOperations(): ), rx.box( rx.foreach( - LiteralVar.create(list(range(0, 3))).to(ArrayVar, List[int]), + LiteralVar.create(list(range(0, 3))).to(ArrayVar, list[int]), lambda x: rx.foreach( ArrayVar.range(x), lambda y: rx.text(VarOperationState.list1[y], as_="p"), diff --git a/tests/integration/tests_playwright/test_appearance.py b/tests/integration/tests_playwright/test_appearance.py index 60aeeaa6b..d325b183f 100644 --- a/tests/integration/tests_playwright/test_appearance.py +++ b/tests/integration/tests_playwright/test_appearance.py @@ -85,7 +85,7 @@ def light_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]: """ with AppHarness.create( root=tmp_path_factory.mktemp("appearance_app"), - app_source=DefaultLightModeApp, # type: ignore + app_source=DefaultLightModeApp, ) as harness: assert harness.app_instance is not None, "app is not running" yield harness @@ -104,7 +104,7 @@ def dark_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]: """ with AppHarness.create( root=tmp_path_factory.mktemp("appearance_app"), - app_source=DefaultDarkModeApp, # type: ignore + app_source=DefaultDarkModeApp, ) as harness: assert harness.app_instance is not None, "app is not running" yield harness @@ -123,7 +123,7 @@ def system_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]: """ with AppHarness.create( root=tmp_path_factory.mktemp("appearance_app"), - app_source=DefaultSystemModeApp, # type: ignore + app_source=DefaultSystemModeApp, ) as harness: assert harness.app_instance is not None, "app is not running" yield harness @@ -142,7 +142,7 @@ def color_toggle_app(tmp_path_factory) -> Generator[AppHarness, None, None]: """ with AppHarness.create( root=tmp_path_factory.mktemp("appearance_app"), - app_source=ColorToggleApp, # type: ignore + app_source=ColorToggleApp, ) as harness: assert harness.app_instance is not None, "app is not running" yield harness diff --git a/tests/integration/tests_playwright/test_datetime_operations.py b/tests/integration/tests_playwright/test_datetime_operations.py index 5e4506776..2ac516d4a 100644 --- a/tests/integration/tests_playwright/test_datetime_operations.py +++ b/tests/integration/tests_playwright/test_datetime_operations.py @@ -54,7 +54,7 @@ def datetime_operations_app(tmp_path_factory) -> Generator[AppHarness, None, Non """ with AppHarness.create( root=tmp_path_factory.mktemp("datetime_operations_app"), - app_source=DatetimeOperationsApp, # type: ignore + app_source=DatetimeOperationsApp, ) as harness: assert harness.app_instance is not None, "app is not running" yield harness diff --git a/tests/integration/tests_playwright/test_link_hover.py b/tests/integration/tests_playwright/test_link_hover.py index 9510bd358..3c29d769a 100644 --- a/tests/integration/tests_playwright/test_link_hover.py +++ b/tests/integration/tests_playwright/test_link_hover.py @@ -29,7 +29,7 @@ def LinkApp(): def link_app(tmp_path_factory) -> Generator[AppHarness, None, None]: with AppHarness.create( root=tmp_path_factory.mktemp("link_app"), - app_source=LinkApp, # type: ignore + app_source=LinkApp, ) as harness: assert harness.app_instance is not None, "app is not running" yield harness diff --git a/tests/units/compiler/test_compiler.py b/tests/units/compiler/test_compiler.py index 25c351c01..50088e728 100644 --- a/tests/units/compiler/test_compiler.py +++ b/tests/units/compiler/test_compiler.py @@ -92,7 +92,7 @@ def test_compile_import_statement( ), ], ) -def test_compile_imports(import_dict: ParsedImportDict, test_dicts: List[dict]): +def test_compile_imports(import_dict: ParsedImportDict, test_dicts: list[dict]): """Test the compile_imports function. Args: @@ -103,7 +103,7 @@ def test_compile_imports(import_dict: ParsedImportDict, test_dicts: List[dict]): for import_dict, test_dict in zip(imports, test_dicts, strict=True): assert import_dict["lib"] == test_dict["lib"] assert import_dict["default"] == test_dict["default"] - assert sorted(import_dict["rest"]) == test_dict["rest"] # type: ignore + assert sorted(import_dict["rest"]) == test_dict["rest"] # pyright: ignore [reportArgumentType] def test_compile_stylesheets(tmp_path, mocker): @@ -198,7 +198,7 @@ def test_create_document_root(): assert isinstance(root, utils.Html) assert isinstance(root.children[0], utils.DocumentHead) # Default language. - assert root.lang == "en" # type: ignore + assert root.lang == "en" # pyright: ignore [reportAttributeAccessIssue] # No children in head. assert len(root.children[0].children) == 0 @@ -208,13 +208,13 @@ def test_create_document_root(): utils.NextScript.create(src="bar.js"), ] root = utils.create_document_root( - head_components=comps, # type: ignore + head_components=comps, # pyright: ignore [reportArgumentType] html_lang="rx", html_custom_attrs={"project": "reflex"}, ) # Two children in head. assert isinstance(root, utils.Html) assert len(root.children[0].children) == 2 - assert root.lang == "rx" # type: ignore + assert root.lang == "rx" # pyright: ignore [reportAttributeAccessIssue] assert isinstance(root.custom_attrs, dict) assert root.custom_attrs == {"project": "reflex"} diff --git a/tests/units/components/core/test_colors.py b/tests/units/components/core/test_colors.py index c1295fb41..15490e576 100644 --- a/tests/units/components/core/test_colors.py +++ b/tests/units/components/core/test_colors.py @@ -31,37 +31,37 @@ def create_color_var(color): (create_color_var(rx.color("mint", 3)), '"var(--mint-3)"', Color), (create_color_var(rx.color("mint", 3, True)), '"var(--mint-a3)"', Color), ( - create_color_var(rx.color(ColorState.color, ColorState.shade)), # type: ignore + create_color_var(rx.color(ColorState.color, ColorState.shade)), # pyright: ignore [reportArgumentType] f'("var(--"+{color_state_name!s}.color+"-"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade))+")")', Color, ), ( create_color_var( - rx.color(ColorState.color, ColorState.shade, ColorState.alpha) # type: ignore + rx.color(ColorState.color, ColorState.shade, ColorState.alpha) # pyright: ignore [reportArgumentType] ), f'("var(--"+{color_state_name!s}.color+"-"+({color_state_name!s}.alpha ? "a" : "")+(((__to_string) => __to_string.toString())({color_state_name!s}.shade))+")")', Color, ), ( - create_color_var(rx.color(f"{ColorState.color}", f"{ColorState.shade}")), # type: ignore + create_color_var(rx.color(f"{ColorState.color}", f"{ColorState.shade}")), # pyright: ignore [reportArgumentType] f'("var(--"+{color_state_name!s}.color+"-"+{color_state_name!s}.shade+")")', Color, ), ( create_color_var( - rx.color(f"{ColorState.color_part}ato", f"{ColorState.shade}") # type: ignore + rx.color(f"{ColorState.color_part}ato", f"{ColorState.shade}") # pyright: ignore [reportArgumentType] ), f'("var(--"+({color_state_name!s}.color_part+"ato")+"-"+{color_state_name!s}.shade+")")', Color, ), ( - create_color_var(f'{rx.color(ColorState.color, f"{ColorState.shade}")}'), # type: ignore + create_color_var(f'{rx.color(ColorState.color, f"{ColorState.shade}")}'), # pyright: ignore [reportArgumentType] f'("var(--"+{color_state_name!s}.color+"-"+{color_state_name!s}.shade+")")', str, ), ( create_color_var( - f'{rx.color(f"{ColorState.color}", f"{ColorState.shade}")}' # type: ignore + f'{rx.color(f"{ColorState.color}", f"{ColorState.shade}")}' # pyright: ignore [reportArgumentType] ), f'("var(--"+{color_state_name!s}.color+"-"+{color_state_name!s}.shade+")")', str, @@ -81,7 +81,7 @@ def test_color(color, expected, expected_type: Union[Type[str], Type[Color]]): '(true ? "var(--mint-7)" : "var(--tomato-5)")', ), ( - rx.cond(True, rx.color(ColorState.color), rx.color(ColorState.color, 5)), # type: ignore + rx.cond(True, rx.color(ColorState.color), rx.color(ColorState.color, 5)), # pyright: ignore [reportArgumentType, reportCallIssue] f'(true ? ("var(--"+{color_state_name!s}.color+"-7)") : ("var(--"+{color_state_name!s}.color+"-5)"))', ), ( @@ -89,7 +89,7 @@ def test_color(color, expected, expected_type: Union[Type[str], Type[Color]]): "condition", ("first", rx.color("mint")), ("second", rx.color("tomato", 5)), - rx.color(ColorState.color, 2), # type: ignore + rx.color(ColorState.color, 2), # pyright: ignore [reportArgumentType] ), '(() => { switch (JSON.stringify("condition")) {case JSON.stringify("first"): return ("var(--mint-7)");' ' break;case JSON.stringify("second"): return ("var(--tomato-5)"); break;default: ' @@ -98,9 +98,9 @@ def test_color(color, expected, expected_type: Union[Type[str], Type[Color]]): ( rx.match( "condition", - ("first", rx.color(ColorState.color)), # type: ignore - ("second", rx.color(ColorState.color, 5)), # type: ignore - rx.color(ColorState.color, 2), # type: ignore + ("first", rx.color(ColorState.color)), # pyright: ignore [reportArgumentType] + ("second", rx.color(ColorState.color, 5)), # pyright: ignore [reportArgumentType] + rx.color(ColorState.color, 2), # pyright: ignore [reportArgumentType] ), '(() => { switch (JSON.stringify("condition")) {case JSON.stringify("first"): ' f'return (("var(--"+{color_state_name!s}.color+"-7)")); break;case JSON.stringify("second"): ' @@ -133,4 +133,4 @@ def test_radix_color(color, expected): expected (str): The expected custom_style string, radix or literal """ code_block = CodeBlock.create("Hello World", background_color=color) - assert str(code_block.custom_style["backgroundColor"]) == expected # type: ignore + assert str(code_block.custom_style["backgroundColor"]) == expected # pyright: ignore [reportAttributeAccessIssue] diff --git a/tests/units/components/core/test_cond.py b/tests/units/components/core/test_cond.py index e88f35c9a..ac073ed29 100644 --- a/tests/units/components/core/test_cond.py +++ b/tests/units/components/core/test_cond.py @@ -14,7 +14,7 @@ from reflex.vars.base import LiteralVar, Var, computed_var @pytest.fixture def cond_state(request): class CondState(BaseState): - value: request.param["value_type"] = request.param["value"] # noqa + value: request.param["value_type"] = request.param["value"] # pyright: ignore [reportInvalidTypeForm, reportUndefinedVariable] # noqa: F821 return CondState @@ -112,13 +112,13 @@ def test_cond_no_else(): assert isinstance(comp, Fragment) comp = comp.children[0] assert isinstance(comp, Cond) - assert comp.cond._decode() is True # type: ignore - assert comp.comp1.render() == Fragment.create(Text.create("hello")).render() + assert comp.cond._decode() is True + assert comp.comp1.render() == Fragment.create(Text.create("hello")).render() # pyright: ignore [reportOptionalMemberAccess] assert comp.comp2 == Fragment.create() # Props do not support the use of cond without else with pytest.raises(ValueError): - cond(True, "hello") # type: ignore + cond(True, "hello") # pyright: ignore [reportArgumentType] def test_cond_computed_var(): diff --git a/tests/units/components/core/test_html.py b/tests/units/components/core/test_html.py index 79c258dfb..bebb2587d 100644 --- a/tests/units/components/core/test_html.py +++ b/tests/units/components/core/test_html.py @@ -16,7 +16,7 @@ def test_html_many_children(): def test_html_create(): html = Html.create("

Hello !

") - assert str(html.dangerouslySetInnerHTML) == '({ ["__html"] : "

Hello !

" })' # type: ignore + assert str(html.dangerouslySetInnerHTML) == '({ ["__html"] : "

Hello !

" })' # pyright: ignore [reportAttributeAccessIssue] assert ( str(html) == '
Hello !

" })}/>' @@ -32,10 +32,10 @@ def test_html_fstring_create(): html = Html.create(f"

Hello {TestState.myvar}!

") assert ( - str(html.dangerouslySetInnerHTML) # type: ignore + str(html.dangerouslySetInnerHTML) # pyright: ignore [reportAttributeAccessIssue] == f'({{ ["__html"] : ("

Hello "+{TestState.myvar!s}+"!

") }})' ) assert ( str(html) - == f'
' # type: ignore + == f'
' # pyright: ignore [reportAttributeAccessIssue] ) diff --git a/tests/units/components/core/test_match.py b/tests/units/components/core/test_match.py index eaf98414d..e563873ec 100644 --- a/tests/units/components/core/test_match.py +++ b/tests/units/components/core/test_match.py @@ -29,7 +29,7 @@ def test_match_components(): rx.text("default value"), ) match_comp = Match.create(MatchState.value, *match_case_tuples) - match_dict = match_comp.render() # type: ignore + match_dict = match_comp.render() assert match_dict["name"] == "Fragment" [match_child] = match_dict["children"] @@ -151,7 +151,7 @@ def test_match_on_component_without_default(): ) match_comp = Match.create(MatchState.value, *match_case_tuples) - default = match_comp.render()["children"][0]["default"] # type: ignore + default = match_comp.render()["children"][0]["default"] assert isinstance(default, Fragment) diff --git a/tests/units/components/core/test_upload.py b/tests/units/components/core/test_upload.py index 710baa161..efade7b63 100644 --- a/tests/units/components/core/test_upload.py +++ b/tests/units/components/core/test_upload.py @@ -5,7 +5,7 @@ from reflex.components.core.upload import ( StyledUpload, Upload, UploadNamespace, - _on_drop_spec, # type: ignore + _on_drop_spec, # pyright: ignore [reportAttributeAccessIssue] cancel_upload, get_upload_url, ) @@ -60,7 +60,7 @@ def test_upload_create(): up_comp_2 = Upload.create( id="foo_id", - on_drop=UploadStateTest.drop_handler([]), # type: ignore + on_drop=UploadStateTest.drop_handler([]), ) assert isinstance(up_comp_2, Upload) assert up_comp_2.is_used @@ -80,7 +80,7 @@ def test_upload_create(): up_comp_4 = Upload.create( id="foo_id", - on_drop=UploadStateTest.not_drop_handler([]), # type: ignore + on_drop=UploadStateTest.not_drop_handler([]), ) assert isinstance(up_comp_4, Upload) assert up_comp_4.is_used @@ -96,7 +96,7 @@ def test_styled_upload_create(): styled_up_comp_2 = StyledUpload.create( id="foo_id", - on_drop=UploadStateTest.drop_handler([]), # type: ignore + on_drop=UploadStateTest.drop_handler([]), ) assert isinstance(styled_up_comp_2, StyledUpload) assert styled_up_comp_2.is_used @@ -116,7 +116,7 @@ def test_styled_upload_create(): styled_up_comp_4 = StyledUpload.create( id="foo_id", - on_drop=UploadStateTest.not_drop_handler([]), # type: ignore + on_drop=UploadStateTest.not_drop_handler([]), ) assert isinstance(styled_up_comp_4, StyledUpload) assert styled_up_comp_4.is_used diff --git a/tests/units/components/datadisplay/test_code.py b/tests/units/components/datadisplay/test_code.py index 6b7168756..db0120fe1 100644 --- a/tests/units/components/datadisplay/test_code.py +++ b/tests/units/components/datadisplay/test_code.py @@ -10,4 +10,4 @@ from reflex.components.datadisplay.code import CodeBlock, Theme def test_code_light_dark_theme(theme, expected): code_block = CodeBlock.create(theme=theme) - assert code_block.theme._js_expr == expected # type: ignore + assert code_block.theme._js_expr == expected # pyright: ignore [reportAttributeAccessIssue] diff --git a/tests/units/components/datadisplay/test_datatable.py b/tests/units/components/datadisplay/test_datatable.py index a8f966d7e..2dece464a 100644 --- a/tests/units/components/datadisplay/test_datatable.py +++ b/tests/units/components/datadisplay/test_datatable.py @@ -14,7 +14,8 @@ from reflex.utils.serializers import serialize, serialize_dataframe pytest.param( { "data": pd.DataFrame( - [["foo", "bar"], ["foo1", "bar1"]], columns=["column1", "column2"] + [["foo", "bar"], ["foo1", "bar1"]], + columns=["column1", "column2"], # pyright: ignore [reportArgumentType] ) }, "data", @@ -114,7 +115,8 @@ def test_computed_var_without_annotation(fixture, request, err_msg, is_data_fram def test_serialize_dataframe(): """Test if dataframe is serialized correctly.""" df = pd.DataFrame( - [["foo", "bar"], ["foo1", "bar1"]], columns=["column1", "column2"] + [["foo", "bar"], ["foo1", "bar1"]], + columns=["column1", "column2"], # pyright: ignore [reportArgumentType] ) value = serialize(df) assert value == serialize_dataframe(df) diff --git a/tests/units/components/datadisplay/test_shiki_code.py b/tests/units/components/datadisplay/test_shiki_code.py index eb473ba06..cc05c35b0 100644 --- a/tests/units/components/datadisplay/test_shiki_code.py +++ b/tests/units/components/datadisplay/test_shiki_code.py @@ -95,7 +95,7 @@ def test_create_shiki_code_block( # Test that the first child is the code code_block_component = component.children[0] - assert code_block_component.code._var_value == expected_first_child # type: ignore + assert code_block_component.code._var_value == expected_first_child # pyright: ignore [reportAttributeAccessIssue] applied_styles = component.style for key, value in expected_styles.items(): @@ -128,12 +128,12 @@ def test_create_shiki_high_level_code_block( # Test that the first child is the code block component code_block_component = component.children[0] - assert code_block_component.code._var_value == children[0] # type: ignore + assert code_block_component.code._var_value == children[0] # pyright: ignore [reportAttributeAccessIssue] # Check if the transformer is set correctly if expected if expected_transformers: exp_trans_names = [t.__name__ for t in expected_transformers] - for transformer in code_block_component.transformers._var_value: # type: ignore + for transformer in code_block_component.transformers._var_value: # pyright: ignore [reportAttributeAccessIssue] assert type(transformer).__name__ in exp_trans_names # Check if the second child is the copy button if can_copy is True @@ -161,12 +161,12 @@ def test_shiki_high_level_code_block_theme_language_mapping(children, props): if "theme" in props: assert component.children[ 0 - ].theme._var_value == ShikiHighLevelCodeBlock._map_themes(props["theme"]) # type: ignore + ].theme._var_value == ShikiHighLevelCodeBlock._map_themes(props["theme"]) # pyright: ignore [reportAttributeAccessIssue] # Test that the language is mapped correctly if "language" in props: assert component.children[ 0 - ].language._var_value == ShikiHighLevelCodeBlock._map_languages( # type: ignore + ].language._var_value == ShikiHighLevelCodeBlock._map_languages( # pyright: ignore [reportAttributeAccessIssue] props["language"] ) diff --git a/tests/units/components/forms/test_form.py b/tests/units/components/forms/test_form.py index 5f3ba2d37..69b5e7b63 100644 --- a/tests/units/components/forms/test_form.py +++ b/tests/units/components/forms/test_form.py @@ -10,7 +10,7 @@ def test_render_on_submit(): _var_type=EventChain, ) f = Form.create(on_submit=submit_it) - exp_submit_name = f"handleSubmit_{f.handle_submit_unique_name}" # type: ignore + exp_submit_name = f"handleSubmit_{f.handle_submit_unique_name}" # pyright: ignore [reportAttributeAccessIssue] assert f"onSubmit={{{exp_submit_name}}}" in f.render()["props"] diff --git a/tests/units/components/media/test_image.py b/tests/units/components/media/test_image.py index 742bd8c38..519ca735e 100644 --- a/tests/units/components/media/test_image.py +++ b/tests/units/components/media/test_image.py @@ -4,7 +4,7 @@ import pytest from PIL.Image import Image as Img import reflex as rx -from reflex.components.next.image import Image # type: ignore +from reflex.components.next.image import Image from reflex.utils.serializers import serialize, serialize_image from reflex.vars.sequence import StringVar @@ -17,7 +17,7 @@ def pil_image() -> Img: A random PIL image. """ imarray = np.random.rand(100, 100, 3) * 255 - return PIL.Image.fromarray(imarray.astype("uint8")).convert("RGBA") # type: ignore + return PIL.Image.fromarray(imarray.astype("uint8")).convert("RGBA") # pyright: ignore [reportAttributeAccessIssue] def test_serialize_image(pil_image: Img): @@ -36,13 +36,13 @@ def test_set_src_str(): """Test that setting the src works.""" image = rx.image(src="pic2.jpeg") # when using next/image, we explicitly create a _var_is_str Var - assert str(image.src) in ( # type: ignore + assert str(image.src) in ( # pyright: ignore [reportAttributeAccessIssue] '"pic2.jpeg"', "'pic2.jpeg'", "`pic2.jpeg`", ) # For plain rx.el.img, an explicit var is not created, so the quoting happens later - # assert str(image.src) == "pic2.jpeg" # type: ignore #noqa: ERA001 + # assert str(image.src) == "pic2.jpeg" #noqa: ERA001 def test_set_src_img(pil_image: Img): @@ -52,7 +52,7 @@ def test_set_src_img(pil_image: Img): pil_image: The image to serialize. """ image = Image.create(src=pil_image) - assert str(image.src._js_expr) == '"' + serialize_image(pil_image) + '"' # type: ignore + assert str(image.src._js_expr) == '"' + serialize_image(pil_image) + '"' # pyright: ignore [reportAttributeAccessIssue] def test_render(pil_image: Img): @@ -62,4 +62,4 @@ def test_render(pil_image: Img): pil_image: The image to serialize. """ image = Image.create(src=pil_image) - assert isinstance(image.src, StringVar) # type: ignore + assert isinstance(image.src, StringVar) # pyright: ignore [reportAttributeAccessIssue] diff --git a/tests/units/components/test_component.py b/tests/units/components/test_component.py index 6ea459142..26e530f7c 100644 --- a/tests/units/components/test_component.py +++ b/tests/units/components/test_component.py @@ -452,8 +452,8 @@ def test_add_style(component1, component2): component1: Style({"color": "white"}), component2: Style({"color": "black"}), } - c1 = component1()._add_style_recursive(style) # type: ignore - c2 = component2()._add_style_recursive(style) # type: ignore + c1 = component1()._add_style_recursive(style) + c2 = component2()._add_style_recursive(style) assert str(c1.style["color"]) == '"white"' assert str(c2.style["color"]) == '"black"' @@ -469,8 +469,8 @@ def test_add_style_create(component1, component2): component1.create: Style({"color": "white"}), component2.create: Style({"color": "black"}), } - c1 = component1()._add_style_recursive(style) # type: ignore - c2 = component2()._add_style_recursive(style) # type: ignore + c1 = component1()._add_style_recursive(style) + c2 = component2()._add_style_recursive(style) assert str(c1.style["color"]) == '"white"' assert str(c2.style["color"]) == '"black"' @@ -1363,17 +1363,17 @@ class EventState(rx.State): id="fstring-background_color", ), pytest.param( - rx.fragment(style={"background_color": TEST_VAR}), # type: ignore + rx.fragment(style={"background_color": TEST_VAR}), # pyright: ignore [reportArgumentType] [STYLE_VAR], id="direct-style-background_color", ), pytest.param( - rx.fragment(style={"background_color": f"foo{TEST_VAR}bar"}), # type: ignore + rx.fragment(style={"background_color": f"foo{TEST_VAR}bar"}), # pyright: ignore [reportArgumentType] [STYLE_VAR], id="fstring-style-background_color", ), pytest.param( - rx.fragment(on_click=EVENT_CHAIN_VAR), # type: ignore + rx.fragment(on_click=EVENT_CHAIN_VAR), [EVENT_CHAIN_VAR], id="direct-event-chain", ), @@ -1383,17 +1383,17 @@ class EventState(rx.State): id="direct-event-handler", ), pytest.param( - rx.fragment(on_click=EventState.handler2(TEST_VAR)), # type: ignore + rx.fragment(on_click=EventState.handler2(TEST_VAR)), # pyright: ignore [reportCallIssue] [ARG_VAR, TEST_VAR], id="direct-event-handler-arg", ), pytest.param( - rx.fragment(on_click=EventState.handler2(EventState.v)), # type: ignore + rx.fragment(on_click=EventState.handler2(EventState.v)), # pyright: ignore [reportCallIssue] [ARG_VAR, EventState.v], id="direct-event-handler-arg2", ), pytest.param( - rx.fragment(on_click=lambda: EventState.handler2(TEST_VAR)), # type: ignore + rx.fragment(on_click=lambda: EventState.handler2(TEST_VAR)), # pyright: ignore [reportCallIssue] [ARG_VAR, TEST_VAR], id="direct-event-handler-lambda", ), @@ -1482,7 +1482,7 @@ def test_instantiate_all_components(): comp_name for submodule_list in component_nested_list for comp_name in submodule_list - ]: # type: ignore + ]: if component_name in untested_components: continue component = getattr( @@ -1555,11 +1555,11 @@ def test_validate_valid_children(): ) valid_component1( - rx.cond( # type: ignore + rx.cond( True, rx.fragment(valid_component2()), rx.fragment( - rx.foreach(LiteralVar.create([1, 2, 3]), lambda x: valid_component2(x)) # type: ignore + rx.foreach(LiteralVar.create([1, 2, 3]), lambda x: valid_component2(x)) ), ) ) @@ -1614,12 +1614,12 @@ def test_validate_valid_parents(): ) valid_component2( - rx.cond( # type: ignore + rx.cond( True, rx.fragment(valid_component3()), rx.fragment( rx.foreach( - LiteralVar.create([1, 2, 3]), # type: ignore + LiteralVar.create([1, 2, 3]), lambda x: valid_component2(valid_component3(x)), ) ), @@ -1682,13 +1682,13 @@ def test_validate_invalid_children(): with pytest.raises(ValueError): valid_component4( - rx.cond( # type: ignore + rx.cond( True, rx.fragment(invalid_component()), rx.fragment( rx.foreach( LiteralVar.create([1, 2, 3]), lambda x: invalid_component(x) - ) # type: ignore + ) ), ) ) @@ -1870,7 +1870,7 @@ def test_invalid_event_trigger(): ) def test_component_add_imports(tags): class BaseComponent(Component): - def _get_imports(self) -> ImportDict: + def _get_imports(self) -> ImportDict: # pyright: ignore [reportIncompatibleMethodOverride] return {} class Reference(Component): @@ -1882,7 +1882,7 @@ def test_component_add_imports(tags): ) class TestBase(Component): - def add_imports( + def add_imports( # pyright: ignore [reportIncompatibleMethodOverride] self, ) -> Dict[str, Union[str, ImportVar, List[str], List[ImportVar]]]: return {"foo": "bar"} @@ -1914,7 +1914,7 @@ def test_component_add_hooks(): pass class GrandchildComponent1(ChildComponent1): - def add_hooks(self): + def add_hooks(self): # pyright: ignore [reportIncompatibleMethodOverride] return [ "const hook2 = 43", "const hook3 = 44", @@ -1927,11 +1927,11 @@ def test_component_add_hooks(): ] class GrandchildComponent2(ChildComponent1): - def _get_hooks(self): + def _get_hooks(self): # pyright: ignore [reportIncompatibleMethodOverride] return "const hook5 = 46" class GreatGrandchildComponent2(GrandchildComponent2): - def add_hooks(self): + def add_hooks(self): # pyright: ignore [reportIncompatibleMethodOverride] return [ "const hook2 = 43", "const hook6 = 47", @@ -2006,7 +2006,7 @@ def test_component_add_custom_code(): ] class GrandchildComponent2(ChildComponent1): - def _get_custom_code(self): + def _get_custom_code(self): # pyright: ignore [reportIncompatibleMethodOverride] return "const custom_code5 = 46" class GreatGrandchildComponent2(GrandchildComponent2): @@ -2102,11 +2102,11 @@ def test_add_style_embedded_vars(test_state: BaseState): test_state: A test state. """ v0 = LiteralVar.create("parent")._replace( - merge_var_data=VarData(hooks={"useParent": None}), # type: ignore + merge_var_data=VarData(hooks={"useParent": None}), ) v1 = rx.color("plum", 10) v2 = LiteralVar.create("text")._replace( - merge_var_data=VarData(hooks={"useText": None}), # type: ignore + merge_var_data=VarData(hooks={"useText": None}), ) class ParentComponent(Component): @@ -2120,7 +2120,7 @@ def test_add_style_embedded_vars(test_state: BaseState): class StyledComponent(ParentComponent): tag = "StyledComponent" - def add_style(self): + def add_style(self): # pyright: ignore [reportIncompatibleMethodOverride] return { "color": v1, "fake": v2, diff --git a/tests/units/components/typography/test_markdown.py b/tests/units/components/typography/test_markdown.py index 5e9abbb1f..12f3b0dbe 100644 --- a/tests/units/components/typography/test_markdown.py +++ b/tests/units/components/typography/test_markdown.py @@ -29,8 +29,8 @@ def test_get_component(tag, expected): expected: The expected component. """ md = Markdown.create("# Hello") - assert tag in md.component_map # type: ignore - assert md.get_component(tag).tag == expected # type: ignore + assert tag in md.component_map # pyright: ignore [reportAttributeAccessIssue] + assert md.get_component(tag).tag == expected def test_set_component_map(): @@ -42,8 +42,8 @@ def test_set_component_map(): md = Markdown.create("# Hello", component_map=component_map) # Check that the new tags have been added. - assert md.get_component("h1").tag == "Box" # type: ignore - assert md.get_component("p").tag == "Box" # type: ignore + assert md.get_component("h1").tag == "Box" + assert md.get_component("p").tag == "Box" # Make sure the old tags are still there. - assert md.get_component("h2").tag == "Heading" # type: ignore + assert md.get_component("h2").tag == "Heading" diff --git a/tests/units/conftest.py b/tests/units/conftest.py index 8c1ffe532..2ee290ea3 100644 --- a/tests/units/conftest.py +++ b/tests/units/conftest.py @@ -95,7 +95,7 @@ def upload_sub_state_event_spec(): Returns: Event Spec. """ - return EventSpec(handler=SubUploadState.handle_upload, upload=True) # type: ignore + return EventSpec(handler=SubUploadState.handle_upload, upload=True) # pyright: ignore [reportCallIssue] @pytest.fixture @@ -105,7 +105,7 @@ def upload_event_spec(): Returns: Event Spec. """ - return EventSpec(handler=UploadState.handle_upload1, upload=True) # type: ignore + return EventSpec(handler=UploadState.handle_upload1, upload=True) # pyright: ignore [reportCallIssue] @pytest.fixture @@ -143,7 +143,7 @@ def sqlite_db_config_values(base_db_config_values) -> Dict: @pytest.fixture -def router_data_headers() -> Dict[str, str]: +def router_data_headers() -> dict[str, str]: """Router data headers. Returns: @@ -170,7 +170,7 @@ def router_data_headers() -> Dict[str, str]: @pytest.fixture -def router_data(router_data_headers) -> Dict[str, str]: +def router_data(router_data_headers: dict[str, str]) -> dict[str, str | dict]: """Router data. Args: @@ -179,7 +179,7 @@ def router_data(router_data_headers) -> Dict[str, str]: Returns: Dict of router data. """ - return { # type: ignore + return { "pathname": "/", "query": {}, "token": "b181904c-3953-4a79-dc18-ae9518c22f05", diff --git a/tests/units/states/mutation.py b/tests/units/states/mutation.py index b05f558a1..ad658bbd0 100644 --- a/tests/units/states/mutation.py +++ b/tests/units/states/mutation.py @@ -18,7 +18,7 @@ class DictMutationTestState(BaseState): def add_age(self): """Add an age to the dict.""" - self.details.update({"age": 20}) # type: ignore + self.details.update({"age": 20}) # pyright: ignore [reportCallIssue, reportArgumentType] def change_name(self): """Change the name in the dict.""" diff --git a/tests/units/test_app.py b/tests/units/test_app.py index 80e0be5fd..074e7f2ef 100644 --- a/tests/units/test_app.py +++ b/tests/units/test_app.py @@ -133,7 +133,7 @@ def test_model() -> Type[Model]: A default model. """ - class TestModel(Model, table=True): # type: ignore + class TestModel(Model, table=True): pass return TestModel @@ -147,7 +147,7 @@ def test_model_auth() -> Type[Model]: A default model. """ - class TestModelAuth(Model, table=True): # type: ignore + class TestModelAuth(Model, table=True): """A test model with auth.""" pass @@ -185,19 +185,19 @@ def test_custom_auth_admin() -> Type[AuthProvider]: login_path: str = "/login" logout_path: str = "/logout" - def login(self): + def login(self): # pyright: ignore [reportIncompatibleMethodOverride] """Login.""" pass - def is_authenticated(self): + def is_authenticated(self): # pyright: ignore [reportIncompatibleMethodOverride] """Is authenticated.""" pass - def get_admin_user(self): + def get_admin_user(self): # pyright: ignore [reportIncompatibleMethodOverride] """Get admin user.""" pass - def logout(self): + def logout(self): # pyright: ignore [reportIncompatibleMethodOverride] """Logout.""" pass @@ -419,7 +419,7 @@ async def test_initialize_with_state(test_state: Type[ATestState], token: str): # Get a state for a given token. state = await app.state_manager.get_state(_substate_key(token, test_state)) assert isinstance(state, test_state) - assert state.var == 0 # type: ignore + assert state.var == 0 if isinstance(app.state_manager, StateManagerRedis): await app.state_manager.close() @@ -441,8 +441,8 @@ async def test_set_and_get_state(test_state): # Get the default state for each token. state1 = await app.state_manager.get_state(token1) state2 = await app.state_manager.get_state(token2) - assert state1.var == 0 # type: ignore - assert state2.var == 0 # type: ignore + assert state1.var == 0 + assert state2.var == 0 # Set the vars to different values. state1.var = 1 @@ -453,8 +453,8 @@ async def test_set_and_get_state(test_state): # Get the states again and check the values. state1 = await app.state_manager.get_state(token1) state2 = await app.state_manager.get_state(token2) - assert state1.var == 1 # type: ignore - assert state2.var == 2 # type: ignore + assert state1.var == 1 + assert state2.var == 2 if isinstance(app.state_manager, StateManagerRedis): await app.state_manager.close() @@ -469,7 +469,7 @@ async def test_dynamic_var_event(test_state: Type[ATestState], token: str): test_state: State Fixture. token: a Token. """ - state = test_state() # type: ignore + state = test_state() # pyright: ignore [reportCallIssue] state.add_var("int_val", int, 0) result = await state._process( Event( @@ -772,7 +772,7 @@ async def test_upload_file(tmp_path, state, delta, token: str, mocker): # The App state must be the "root" of the state tree app = App() app._enable_state() - app.event_namespace.emit = AsyncMock() # type: ignore + app.event_namespace.emit = AsyncMock() # pyright: ignore [reportOptionalMemberAccess] current_state = await app.state_manager.get_state(_substate_key(token, state)) data = b"This is binary data" @@ -795,7 +795,7 @@ async def test_upload_file(tmp_path, state, delta, token: str, mocker): file=bio, ) upload_fn = upload(app) - streaming_response = await upload_fn(request_mock, [file1, file2]) + streaming_response = await upload_fn(request_mock, [file1, file2]) # pyright: ignore [reportFunctionMemberAccess] async for state_update in streaming_response.body_iterator: assert ( state_update @@ -917,7 +917,7 @@ class DynamicState(BaseState): """ return self.dynamic - on_load_internal = OnLoadInternalState.on_load_internal.fn + on_load_internal = OnLoadInternalState.on_load_internal.fn # pyright: ignore [reportFunctionMemberAccess] def test_dynamic_arg_shadow( @@ -941,7 +941,7 @@ def test_dynamic_arg_shadow( app = app_module_mock.app = App(_state=DynamicState) assert app._state is not None with pytest.raises(NameError): - app.add_page(index_page, route=route, on_load=DynamicState.on_load) # type: ignore + app.add_page(index_page, route=route, on_load=DynamicState.on_load) def test_multiple_dynamic_args( @@ -993,7 +993,7 @@ async def test_dynamic_route_var_route_change_completed_on_load( app = app_module_mock.app = App(_state=DynamicState) assert app._state is not None assert arg_name not in app._state.vars - app.add_page(index_page, route=route, on_load=DynamicState.on_load) # type: ignore + app.add_page(index_page, route=route, on_load=DynamicState.on_load) assert arg_name in app._state.vars assert arg_name in app._state.computed_vars assert app._state.computed_vars[arg_name]._deps(objclass=DynamicState) == { @@ -1022,7 +1022,7 @@ async def test_dynamic_route_var_route_change_completed_on_load( def _dynamic_state_event(name, val, **kwargs): return _event( - name=format.format_event_handler(getattr(DynamicState, name)), # type: ignore + name=format.format_event_handler(getattr(DynamicState, name)), val=val, **kwargs, ) @@ -1190,7 +1190,7 @@ async def test_process_events(mocker, token: str): pass assert (await app.state_manager.get_state(event.substate_token)).value == 5 - assert app._postprocess.call_count == 6 + assert app._postprocess.call_count == 6 # pyright: ignore [reportFunctionMemberAccess] if isinstance(app.state_manager, StateManagerRedis): await app.state_manager.close() @@ -1226,7 +1226,7 @@ def test_overlay_component( assert app.overlay_component is None elif isinstance(exp_page_child, OverlayFragment): assert app.overlay_component is not None - generated_component = app._generate_component(app.overlay_component) # type: ignore + generated_component = app._generate_component(app.overlay_component) assert isinstance(generated_component, OverlayFragment) assert isinstance( generated_component.children[0], @@ -1235,7 +1235,7 @@ def test_overlay_component( else: assert app.overlay_component is not None assert isinstance( - app._generate_component(app.overlay_component), # type: ignore + app._generate_component(app.overlay_component), exp_page_child, ) @@ -1248,7 +1248,7 @@ def test_overlay_component( if exp_page_child is not None: assert len(page.children) == 3 children_types = (type(child) for child in page.children) - assert exp_page_child in children_types + assert exp_page_child in children_types # pyright: ignore [reportOperatorIssue] else: assert len(page.children) == 2 @@ -1315,19 +1315,19 @@ def test_app_wrap_priority(compilable_app: tuple[App, Path]): class Fragment1(Component): tag = "Fragment1" - def _get_app_wrap_components(self) -> dict[tuple[int, str], Component]: + def _get_app_wrap_components(self) -> dict[tuple[int, str], Component]: # pyright: ignore [reportIncompatibleMethodOverride] return {(99, "Box"): rx.box()} class Fragment2(Component): tag = "Fragment2" - def _get_app_wrap_components(self) -> dict[tuple[int, str], Component]: + def _get_app_wrap_components(self) -> dict[tuple[int, str], Component]: # pyright: ignore [reportIncompatibleMethodOverride] return {(50, "Text"): rx.text()} class Fragment3(Component): tag = "Fragment3" - def _get_app_wrap_components(self) -> dict[tuple[int, str], Component]: + def _get_app_wrap_components(self) -> dict[tuple[int, str], Component]: # pyright: ignore [reportIncompatibleMethodOverride] return {(10, "Fragment2"): Fragment2.create()} def page(): @@ -1448,11 +1448,11 @@ def test_generate_component(): "Bar", ) - comp = App._generate_component(index) # type: ignore + comp = App._generate_component(index) assert isinstance(comp, Component) with pytest.raises(exceptions.MatchTypeError): - App._generate_component(index_mismatch) # type: ignore + App._generate_component(index_mismatch) # pyright: ignore [reportArgumentType] def test_add_page_component_returning_tuple(): @@ -1467,8 +1467,8 @@ def test_add_page_component_returning_tuple(): def page2(): return (rx.text("third"),) - app.add_page(index) # type: ignore - app.add_page(page2) # type: ignore + app.add_page(index) # pyright: ignore [reportArgumentType] + app.add_page(page2) # pyright: ignore [reportArgumentType] app._compile_page("index") app._compile_page("page2") @@ -1477,17 +1477,17 @@ def test_add_page_component_returning_tuple(): assert isinstance(fragment_wrapper, Fragment) first_text = fragment_wrapper.children[0] assert isinstance(first_text, Text) - assert str(first_text.children[0].contents) == '"first"' # type: ignore + assert str(first_text.children[0].contents) == '"first"' # pyright: ignore [reportAttributeAccessIssue] second_text = fragment_wrapper.children[1] assert isinstance(second_text, Text) - assert str(second_text.children[0].contents) == '"second"' # type: ignore + assert str(second_text.children[0].contents) == '"second"' # pyright: ignore [reportAttributeAccessIssue] # Test page with trailing comma. page2_fragment_wrapper = app._pages["page2"].children[0] assert isinstance(page2_fragment_wrapper, Fragment) third_text = page2_fragment_wrapper.children[0] assert isinstance(third_text, Text) - assert str(third_text.children[0].contents) == '"third"' # type: ignore + assert str(third_text.children[0].contents) == '"third"' # pyright: ignore [reportAttributeAccessIssue] @pytest.mark.parametrize("export", (True, False)) @@ -1525,7 +1525,7 @@ def test_app_with_transpile_packages(compilable_app: tuple[App, Path], export: b next_config = (web_dir / "next.config.js").read_text() transpile_packages_match = re.search(r"transpilePackages: (\[.*?\])", next_config) - transpile_packages_json = transpile_packages_match.group(1) # type: ignore + transpile_packages_json = transpile_packages_match.group(1) # pyright: ignore [reportOptionalMemberAccess] transpile_packages = sorted(json.loads(transpile_packages_json)) assert transpile_packages == [ diff --git a/tests/units/test_config.py b/tests/units/test_config.py index e5d4622bd..88d8b5f2f 100644 --- a/tests/units/test_config.py +++ b/tests/units/test_config.py @@ -21,7 +21,7 @@ from reflex.constants import Endpoint, Env def test_requires_app_name(): """Test that a config requires an app_name.""" with pytest.raises(ValueError): - rx.Config() # type: ignore + rx.Config() def test_set_app_name(base_config_values): @@ -207,7 +207,7 @@ def test_replace_defaults( exp_config_values: The expected config values. """ mock_os_env = os.environ.copy() - monkeypatch.setattr(reflex.config.os, "environ", mock_os_env) # type: ignore + monkeypatch.setattr(reflex.config.os, "environ", mock_os_env) mock_os_env.update({k: str(v) for k, v in env_vars.items()}) c = rx.Config(app_name="a", **config_kwargs) c._set_persistent(**set_persistent_vars) diff --git a/tests/units/test_event.py b/tests/units/test_event.py index 520e876df..5e47991da 100644 --- a/tests/units/test_event.py +++ b/tests/units/test_event.py @@ -72,7 +72,7 @@ def test_call_event_handler(): ) # Passing args as strings should format differently. - event_spec = handler("first", "second") # type: ignore + event_spec = handler("first", "second") assert ( format.format_event(event_spec) == 'Event("test_fn_with_args", {arg1:"first",arg2:"second"})' @@ -80,7 +80,7 @@ def test_call_event_handler(): first, second = 123, "456" handler = EventHandler(fn=test_fn_with_args) - event_spec = handler(first, second) # type: ignore + event_spec = handler(first, second) assert ( format.format_event(event_spec) == 'Event("test_fn_with_args", {arg1:123,arg2:"456"})' @@ -94,7 +94,7 @@ def test_call_event_handler(): handler = EventHandler(fn=test_fn_with_args) with pytest.raises(TypeError): - handler(test_fn) # type: ignore + handler(test_fn) def test_call_event_handler_partial(): @@ -416,7 +416,7 @@ def test_event_actions_on_state(): assert isinstance(handler, EventHandler) assert not handler.event_actions - sp_handler = EventActionState.handler.stop_propagation + sp_handler = EventActionState.handler.stop_propagation # pyright: ignore [reportFunctionMemberAccess] assert sp_handler.event_actions == {"stopPropagation": True} # should NOT affect other references to the handler assert not handler.event_actions diff --git a/tests/units/test_health_endpoint.py b/tests/units/test_health_endpoint.py index 6d12d79d6..5b3aedc00 100644 --- a/tests/units/test_health_endpoint.py +++ b/tests/units/test_health_endpoint.py @@ -122,9 +122,9 @@ async def test_health( # Call the async health function response = await health() - print(json.loads(response.body)) + print(json.loads(response.body)) # pyright: ignore [reportArgumentType] print(expected_status) # Verify the response content and status code assert response.status_code == expected_code - assert json.loads(response.body) == expected_status + assert json.loads(response.body) == expected_status # pyright: ignore [reportArgumentType] diff --git a/tests/units/test_model.py b/tests/units/test_model.py index 0a83f39ec..b17538248 100644 --- a/tests/units/test_model.py +++ b/tests/units/test_model.py @@ -86,7 +86,7 @@ def test_automigration( assert versions.exists() # initial table - class AlembicThing(Model, table=True): # type: ignore + class AlembicThing(Model, table=True): # pyright: ignore [reportRedeclaration] t1: str with Model.get_db_engine().connect() as connection: @@ -105,7 +105,7 @@ def test_automigration( model_registry.get_metadata().clear() # Create column t2, mark t1 as optional with default - class AlembicThing(Model, table=True): # type: ignore + class AlembicThing(Model, table=True): # pyright: ignore [reportRedeclaration] t1: Optional[str] = "default" t2: str = "bar" @@ -125,7 +125,7 @@ def test_automigration( model_registry.get_metadata().clear() # Drop column t1 - class AlembicThing(Model, table=True): # type: ignore + class AlembicThing(Model, table=True): # pyright: ignore [reportRedeclaration] t2: str = "bar" assert Model.migrate(autogenerate=True) @@ -138,7 +138,7 @@ def test_automigration( assert result[1].t2 == "baz" # Add table - class AlembicSecond(Model, table=True): # type: ignore + class AlembicSecond(Model, table=True): a: int = 42 b: float = 4.2 @@ -160,14 +160,14 @@ def test_automigration( # drop table (AlembicSecond) model_registry.get_metadata().clear() - class AlembicThing(Model, table=True): # type: ignore + class AlembicThing(Model, table=True): # pyright: ignore [reportRedeclaration] t2: str = "bar" assert Model.migrate(autogenerate=True) assert len(list(versions.glob("*.py"))) == 5 with reflex.model.session() as session: - with pytest.raises(sqlalchemy.exc.OperationalError) as errctx: # type: ignore + with pytest.raises(sqlalchemy.exc.OperationalError) as errctx: session.exec(sqlmodel.select(AlembicSecond)).all() assert errctx.match(r"no such table: alembicsecond") # first table should still exist @@ -178,7 +178,7 @@ def test_automigration( model_registry.get_metadata().clear() - class AlembicThing(Model, table=True): # type: ignore + class AlembicThing(Model, table=True): # changing column type not supported by default t2: int = 42 diff --git a/tests/units/test_prerequisites.py b/tests/units/test_prerequisites.py index cf655d6cd..3bd029077 100644 --- a/tests/units/test_prerequisites.py +++ b/tests/units/test_prerequisites.py @@ -100,7 +100,7 @@ def test_transpile_packages(transpile_packages, expected_transpile_packages): transpile_packages=transpile_packages, ) transpile_packages_match = re.search(r"transpilePackages: (\[.*?\])", output) - transpile_packages_json = transpile_packages_match.group(1) # type: ignore + transpile_packages_json = transpile_packages_match.group(1) # pyright: ignore [reportOptionalMemberAccess] actual_transpile_packages = sorted(json.loads(transpile_packages_json)) assert actual_transpile_packages == expected_transpile_packages diff --git a/tests/units/test_sqlalchemy.py b/tests/units/test_sqlalchemy.py index 23e315785..4434f5ee1 100644 --- a/tests/units/test_sqlalchemy.py +++ b/tests/units/test_sqlalchemy.py @@ -59,7 +59,7 @@ def test_automigration( id: Mapped[Optional[int]] = mapped_column(primary_key=True, default=None) # initial table - class AlembicThing(ModelBase): # pyright: ignore[reportGeneralTypeIssues] + class AlembicThing(ModelBase): # pyright: ignore[reportRedeclaration] t1: Mapped[str] = mapped_column(default="") with Model.get_db_engine().connect() as connection: @@ -78,7 +78,7 @@ def test_automigration( model_registry.get_metadata().clear() # Create column t2, mark t1 as optional with default - class AlembicThing(ModelBase): # pyright: ignore[reportGeneralTypeIssues] + class AlembicThing(ModelBase): # pyright: ignore[reportRedeclaration] t1: Mapped[Optional[str]] = mapped_column(default="default") t2: Mapped[str] = mapped_column(default="bar") @@ -98,7 +98,7 @@ def test_automigration( model_registry.get_metadata().clear() # Drop column t1 - class AlembicThing(ModelBase): # pyright: ignore[reportGeneralTypeIssues] + class AlembicThing(ModelBase): # pyright: ignore[reportRedeclaration] t2: Mapped[str] = mapped_column(default="bar") assert Model.migrate(autogenerate=True) @@ -133,7 +133,7 @@ def test_automigration( # drop table (AlembicSecond) model_registry.get_metadata().clear() - class AlembicThing(ModelBase): # pyright: ignore[reportGeneralTypeIssues] + class AlembicThing(ModelBase): # pyright: ignore[reportRedeclaration] t2: Mapped[str] = mapped_column(default="bar") assert Model.migrate(autogenerate=True) diff --git a/tests/units/test_state.py b/tests/units/test_state.py index dfb068626..b276bad4b 100644 --- a/tests/units/test_state.py +++ b/tests/units/test_state.py @@ -241,7 +241,7 @@ def test_state() -> TestState: Returns: A test state. """ - return TestState() # type: ignore + return TestState() # pyright: ignore [reportCallIssue] @pytest.fixture @@ -431,10 +431,10 @@ def test_default_setters(test_state): def test_class_indexing_with_vars(): """Test that we can index into a state var with another var.""" - prop = TestState.array[TestState.num1] + prop = TestState.array[TestState.num1] # pyright: ignore [reportCallIssue, reportArgumentType] assert str(prop) == f"{TestState.get_name()}.array.at({TestState.get_name()}.num1)" - prop = TestState.mapping["a"][TestState.num1] + prop = TestState.mapping["a"][TestState.num1] # pyright: ignore [reportCallIssue, reportArgumentType] assert ( str(prop) == f'{TestState.get_name()}.mapping["a"].at({TestState.get_name()}.num1)' @@ -554,9 +554,9 @@ def test_get_class_var(): def test_set_class_var(): """Test setting the var of a class.""" with pytest.raises(AttributeError): - TestState.num3 # type: ignore + TestState.num3 # pyright: ignore [reportAttributeAccessIssue] TestState._set_var(Var(_js_expr="num3", _var_type=int)._var_set_state(TestState)) - var = TestState.num3 # type: ignore + var = TestState.num3 # pyright: ignore [reportAttributeAccessIssue] assert var._js_expr == TestState.get_full_name() + ".num3" assert var._var_type is int assert var._var_state == TestState.get_full_name() @@ -848,7 +848,7 @@ async def test_process_event_substate(test_state, child_state, grandchild_state) @pytest.mark.asyncio async def test_process_event_generator(): """Test event handlers that generate multiple updates.""" - gen_state = GenState() # type: ignore + gen_state = GenState() # pyright: ignore [reportCallIssue] event = Event( token="t", name="go", @@ -948,12 +948,12 @@ def test_add_var(): assert not hasattr(ds1, "dynamic_int") ds1.add_var("dynamic_int", int, 42) # Existing instances get the BaseVar - assert ds1.dynamic_int.equals(DynamicState.dynamic_int) # type: ignore + assert ds1.dynamic_int.equals(DynamicState.dynamic_int) # pyright: ignore [reportAttributeAccessIssue] # New instances get an actual value with the default assert DynamicState().dynamic_int == 42 ds1.add_var("dynamic_list", List[int], [5, 10]) - assert ds1.dynamic_list.equals(DynamicState.dynamic_list) # type: ignore + assert ds1.dynamic_list.equals(DynamicState.dynamic_list) # pyright: ignore [reportAttributeAccessIssue] ds2 = DynamicState() assert ds2.dynamic_list == [5, 10] ds2.dynamic_list.append(15) @@ -961,8 +961,8 @@ def test_add_var(): assert DynamicState().dynamic_list == [5, 10] ds1.add_var("dynamic_dict", Dict[str, int], {"k1": 5, "k2": 10}) - assert ds1.dynamic_dict.equals(DynamicState.dynamic_dict) # type: ignore - assert ds2.dynamic_dict.equals(DynamicState.dynamic_dict) # type: ignore + assert ds1.dynamic_dict.equals(DynamicState.dynamic_dict) # pyright: ignore [reportAttributeAccessIssue] + assert ds2.dynamic_dict.equals(DynamicState.dynamic_dict) # pyright: ignore [reportAttributeAccessIssue] assert DynamicState().dynamic_dict == {"k1": 5, "k2": 10} assert DynamicState().dynamic_dict == {"k1": 5, "k2": 10} @@ -1023,7 +1023,7 @@ class InterdependentState(BaseState): Returns: ComputedVar v1x2 multiplied by 2 """ - return self.v1x2 * 2 # type: ignore + return self.v1x2 * 2 @rx.var def _v3(self) -> int: @@ -1270,7 +1270,7 @@ def test_computed_var_cached_depends_on_non_cached(): @rx.var def dep_v(self) -> int: - return self.no_cache_v # type: ignore + return self.no_cache_v @rx.var def comp_v(self) -> int: @@ -1313,7 +1313,7 @@ def test_computed_var_depends_on_parent_non_cached(): class ChildState(ParentState): @rx.var def dep_v(self) -> int: - return self.no_cache_v # type: ignore + return self.no_cache_v ps = ParentState() cs = ps.substates[ChildState.get_name()] @@ -1365,7 +1365,7 @@ def test_cached_var_depends_on_event_handler(use_partial: bool): return counter if use_partial: - HandlerState.handler = functools.partial(HandlerState.handler.fn) + HandlerState.handler = functools.partial(HandlerState.handler.fn) # pyright: ignore [reportFunctionMemberAccess] assert isinstance(HandlerState.handler, functools.partial) else: assert isinstance(HandlerState.handler, EventHandler) @@ -1616,7 +1616,7 @@ async def test_state_with_invalid_yield(capsys, mock_app): id="backend_error", position="top-center", style={"width": "500px"}, - ) # type: ignore + ) # pyright: ignore [reportCallIssue, reportArgumentType] ], token="", ) @@ -1913,7 +1913,7 @@ def mock_app_simple(monkeypatch) -> rx.App: setattr(app_module, CompileVars.APP, app) app._state = TestState - app.event_namespace.emit = CopyingAsyncMock() # type: ignore + app.event_namespace.emit = CopyingAsyncMock() # pyright: ignore [reportOptionalMemberAccess] def _mock_get_app(*args, **kwargs): return app_module @@ -2022,8 +2022,8 @@ async def test_state_proxy(grandchild_state: GrandchildState, mock_app: rx.App): # ensure state update was emitted assert mock_app.event_namespace is not None - mock_app.event_namespace.emit.assert_called_once() - mcall = mock_app.event_namespace.emit.mock_calls[0] + mock_app.event_namespace.emit.assert_called_once() # pyright: ignore [reportFunctionMemberAccess] + mcall = mock_app.event_namespace.emit.mock_calls[0] # pyright: ignore [reportFunctionMemberAccess] assert mcall.args[0] == str(SocketEvent.EVENT) assert mcall.args[1] == StateUpdate( delta={ @@ -2154,7 +2154,7 @@ async def test_background_task_no_block(mock_app: rx.App, token: str): """ router_data = {"query": {}} mock_app.state_manager.state = mock_app._state = BackgroundTaskState - async for update in rx.app.process( # type: ignore + async for update in rx.app.process( mock_app, Event( token=token, @@ -2174,7 +2174,7 @@ async def test_background_task_no_block(mock_app: rx.App, token: str): assert len(mock_app._background_tasks) == 1 # Process another normal event - async for update in rx.app.process( # type: ignore + async for update in rx.app.process( mock_app, Event( token=token, @@ -2224,7 +2224,7 @@ async def test_background_task_no_block(mock_app: rx.App, token: str): assert mock_app.event_namespace is not None emit_mock = mock_app.event_namespace.emit - first_ws_message = emit_mock.mock_calls[0].args[1] + first_ws_message = emit_mock.mock_calls[0].args[1] # pyright: ignore [reportFunctionMemberAccess] assert ( first_ws_message.delta[BackgroundTaskState.get_full_name()].pop("router") is not None @@ -2239,7 +2239,7 @@ async def test_background_task_no_block(mock_app: rx.App, token: str): events=[], final=True, ) - for call in emit_mock.mock_calls[1:5]: + for call in emit_mock.mock_calls[1:5]: # pyright: ignore [reportFunctionMemberAccess] assert call.args[1] == StateUpdate( delta={ BackgroundTaskState.get_full_name(): { @@ -2249,7 +2249,7 @@ async def test_background_task_no_block(mock_app: rx.App, token: str): events=[], final=True, ) - assert emit_mock.mock_calls[-2].args[1] == StateUpdate( + assert emit_mock.mock_calls[-2].args[1] == StateUpdate( # pyright: ignore [reportFunctionMemberAccess] delta={ BackgroundTaskState.get_full_name(): { "order": exp_order, @@ -2260,7 +2260,7 @@ async def test_background_task_no_block(mock_app: rx.App, token: str): events=[], final=True, ) - assert emit_mock.mock_calls[-1].args[1] == StateUpdate( + assert emit_mock.mock_calls[-1].args[1] == StateUpdate( # pyright: ignore [reportFunctionMemberAccess] delta={ BackgroundTaskState.get_full_name(): { "computed_order": exp_order, @@ -2281,7 +2281,7 @@ async def test_background_task_reset(mock_app: rx.App, token: str): """ router_data = {"query": {}} mock_app.state_manager.state = mock_app._state = BackgroundTaskState - async for update in rx.app.process( # type: ignore + async for update in rx.app.process( mock_app, Event( token=token, @@ -2623,10 +2623,10 @@ def test_duplicate_substate_class(mocker): class TestState(BaseState): pass - class ChildTestState(TestState): # type: ignore + class ChildTestState(TestState): # pyright: ignore [reportRedeclaration] pass - class ChildTestState(TestState): # type: ignore # noqa + class ChildTestState(TestState): # noqa: F811 pass return TestState @@ -2664,21 +2664,21 @@ def test_reset_with_mutables(): items: List[List[int]] = default instance = MutableResetState() - assert instance.items.__wrapped__ is not default # type: ignore + assert instance.items.__wrapped__ is not default # pyright: ignore [reportAttributeAccessIssue] assert instance.items == default == copied_default instance.items.append([3, 3]) assert instance.items != default assert instance.items != copied_default instance.reset() - assert instance.items.__wrapped__ is not default # type: ignore + assert instance.items.__wrapped__ is not default # pyright: ignore [reportAttributeAccessIssue] assert instance.items == default == copied_default instance.items.append([3, 3]) assert instance.items != default assert instance.items != copied_default instance.reset() - assert instance.items.__wrapped__ is not default # type: ignore + assert instance.items.__wrapped__ is not default # pyright: ignore [reportAttributeAccessIssue] assert instance.items == default == copied_default instance.items.append([3, 3]) assert instance.items != default @@ -2740,30 +2740,30 @@ def test_state_union_optional(): c3r: Custom3 = Custom3(c2r=Custom2(c1r=Custom1(foo=""))) custom_union: Union[Custom1, Custom2, Custom3] = Custom1(foo="") - assert str(UnionState.c3.c2) == f'{UnionState.c3!s}?.["c2"]' # type: ignore - assert str(UnionState.c3.c2.c1) == f'{UnionState.c3!s}?.["c2"]?.["c1"]' # type: ignore + assert str(UnionState.c3.c2) == f'{UnionState.c3!s}?.["c2"]' # pyright: ignore [reportOptionalMemberAccess] + assert str(UnionState.c3.c2.c1) == f'{UnionState.c3!s}?.["c2"]?.["c1"]' # pyright: ignore [reportOptionalMemberAccess] assert ( - str(UnionState.c3.c2.c1.foo) == f'{UnionState.c3!s}?.["c2"]?.["c1"]?.["foo"]' # type: ignore + str(UnionState.c3.c2.c1.foo) == f'{UnionState.c3!s}?.["c2"]?.["c1"]?.["foo"]' # pyright: ignore [reportOptionalMemberAccess] ) assert ( - str(UnionState.c3.c2.c1r.foo) == f'{UnionState.c3!s}?.["c2"]?.["c1r"]["foo"]' # type: ignore + str(UnionState.c3.c2.c1r.foo) == f'{UnionState.c3!s}?.["c2"]?.["c1r"]["foo"]' # pyright: ignore [reportOptionalMemberAccess] ) - assert str(UnionState.c3.c2r.c1) == f'{UnionState.c3!s}?.["c2r"]["c1"]' # type: ignore + assert str(UnionState.c3.c2r.c1) == f'{UnionState.c3!s}?.["c2r"]["c1"]' # pyright: ignore [reportOptionalMemberAccess] assert ( - str(UnionState.c3.c2r.c1.foo) == f'{UnionState.c3!s}?.["c2r"]["c1"]?.["foo"]' # type: ignore + str(UnionState.c3.c2r.c1.foo) == f'{UnionState.c3!s}?.["c2r"]["c1"]?.["foo"]' # pyright: ignore [reportOptionalMemberAccess] ) assert ( - str(UnionState.c3.c2r.c1r.foo) == f'{UnionState.c3!s}?.["c2r"]["c1r"]["foo"]' # type: ignore + str(UnionState.c3.c2r.c1r.foo) == f'{UnionState.c3!s}?.["c2r"]["c1r"]["foo"]' # pyright: ignore [reportOptionalMemberAccess] ) - assert str(UnionState.c3i.c2) == f'{UnionState.c3i!s}["c2"]' # type: ignore - assert str(UnionState.c3r.c2) == f'{UnionState.c3r!s}["c2"]' # type: ignore - assert UnionState.custom_union.foo is not None # type: ignore - assert UnionState.custom_union.c1 is not None # type: ignore - assert UnionState.custom_union.c1r is not None # type: ignore - assert UnionState.custom_union.c2 is not None # type: ignore - assert UnionState.custom_union.c2r is not None # type: ignore - assert types.is_optional(UnionState.opt_int._var_type) # type: ignore - assert types.is_union(UnionState.int_float._var_type) # type: ignore + assert str(UnionState.c3i.c2) == f'{UnionState.c3i!s}["c2"]' + assert str(UnionState.c3r.c2) == f'{UnionState.c3r!s}["c2"]' + assert UnionState.custom_union.foo is not None # pyright: ignore [reportAttributeAccessIssue] + assert UnionState.custom_union.c1 is not None # pyright: ignore [reportAttributeAccessIssue] + assert UnionState.custom_union.c1r is not None # pyright: ignore [reportAttributeAccessIssue] + assert UnionState.custom_union.c2 is not None # pyright: ignore [reportAttributeAccessIssue] + assert UnionState.custom_union.c2r is not None # pyright: ignore [reportAttributeAccessIssue] + assert types.is_optional(UnionState.opt_int._var_type) # pyright: ignore [reportAttributeAccessIssue, reportOptionalMemberAccess] + assert types.is_union(UnionState.int_float._var_type) # pyright: ignore [reportAttributeAccessIssue] def test_set_base_field_via_setter(): @@ -3360,9 +3360,9 @@ config = rx.Config( from reflex.state import State, StateManager state_manager = StateManager.create(state=State) - assert state_manager.lock_expiration == expected_values[0] # type: ignore - assert state_manager.token_expiration == expected_values[1] # type: ignore - assert state_manager.lock_warning_threshold == expected_values[2] # type: ignore + assert state_manager.lock_expiration == expected_values[0] # pyright: ignore [reportAttributeAccessIssue] + assert state_manager.token_expiration == expected_values[1] # pyright: ignore [reportAttributeAccessIssue] + assert state_manager.lock_warning_threshold == expected_values[2] # pyright: ignore [reportAttributeAccessIssue] @pytest.mark.skipif("REDIS_URL" not in os.environ, reason="Test requires redis") @@ -3441,7 +3441,7 @@ def test_mixin_state() -> None: assert "computed" in UsesMixinState.vars assert ( - UsesMixinState(_reflex_internal_init=True)._backend_no_default # type: ignore + UsesMixinState(_reflex_internal_init=True)._backend_no_default # pyright: ignore [reportCallIssue] is not UsesMixinState.backend_vars["_backend_no_default"] ) @@ -3461,7 +3461,7 @@ def test_assignment_to_undeclared_vars(): class State(BaseState): val: str _val: str - __val: str # type: ignore + __val: str # pyright: ignore [reportGeneralTypeIssues] def handle_supported_regular_vars(self): self.val = "no underscore" @@ -3481,8 +3481,8 @@ def test_assignment_to_undeclared_vars(): def handle_var(self): self.value = 20 - state = State() # type: ignore - sub_state = Substate() # type: ignore + state = State() # pyright: ignore [reportCallIssue] + sub_state = Substate() # pyright: ignore [reportCallIssue] with pytest.raises(SetUndefinedStateVarError): state.handle_regular_var() @@ -3544,7 +3544,7 @@ def test_fallback_pickle(): _f: Optional[Callable] = None _g: Any = None - state = DillState(_reflex_internal_init=True) # type: ignore + state = DillState(_reflex_internal_init=True) # pyright: ignore [reportCallIssue] state._o = Obj(_f=lambda: 42) state._f = lambda: 420 @@ -3555,14 +3555,14 @@ def test_fallback_pickle(): assert unpickled_state._o._f() == 42 # Threading locks are unpicklable normally, and raise TypeError instead of PicklingError. - state2 = DillState(_reflex_internal_init=True) # type: ignore + state2 = DillState(_reflex_internal_init=True) # pyright: ignore [reportCallIssue] state2._g = threading.Lock() pk2 = state2._serialize() unpickled_state2 = BaseState._deserialize(pk2) assert isinstance(unpickled_state2._g, type(threading.Lock())) # Some object, like generator, are still unpicklable with dill. - state3 = DillState(_reflex_internal_init=True) # type: ignore + state3 = DillState(_reflex_internal_init=True) # pyright: ignore [reportCallIssue] state3._g = (i for i in range(10)) with pytest.raises(StateSerializationError): @@ -3737,7 +3737,7 @@ class UpcastState(rx.State): assert isinstance(a, list) self.passed = True - def py_unresolvable(self, u: "Unresolvable"): # noqa: D102, F821 # type: ignore + def py_unresolvable(self, u: "Unresolvable"): # noqa: D102, F821 # pyright: ignore [reportUndefinedVariable] assert isinstance(u, list) self.passed = True diff --git a/tests/units/test_style.py b/tests/units/test_style.py index bb585fd22..6ab00d561 100644 --- a/tests/units/test_style.py +++ b/tests/units/test_style.py @@ -356,7 +356,7 @@ def test_style_via_component( style_dict: The style_dict to pass to the component. expected_get_style: The expected style dict. """ - comp = rx.el.div(style=style_dict, **kwargs) # type: ignore + comp = rx.el.div(style=style_dict, **kwargs) # pyright: ignore [reportArgumentType] compare_dict_of_var(comp._get_style(), expected_get_style) @@ -515,17 +515,17 @@ def test_evaluate_style_namespaces(): """Test that namespaces get converted to component create functions.""" style_dict = {rx.text: {"color": "blue"}} assert rx.text.__call__ not in style_dict - style_dict = evaluate_style_namespaces(style_dict) # type: ignore + style_dict = evaluate_style_namespaces(style_dict) # pyright: ignore [reportArgumentType] assert rx.text.__call__ in style_dict def test_style_update_with_var_data(): """Test that .update with a Style containing VarData works.""" red_var = LiteralVar.create("red")._replace( - merge_var_data=VarData(hooks={"const red = true": None}), # type: ignore + merge_var_data=VarData(hooks={"const red = true": None}), ) blue_var = LiteralVar.create("blue")._replace( - merge_var_data=VarData(hooks={"const blue = true": None}), # type: ignore + merge_var_data=VarData(hooks={"const blue = true": None}), ) s1 = Style( diff --git a/tests/units/test_var.py b/tests/units/test_var.py index 51b0d9a2b..899075cdb 100644 --- a/tests/units/test_var.py +++ b/tests/units/test_var.py @@ -288,7 +288,7 @@ def test_create(value, expected): expected: The expected name of the setter function. """ prop = LiteralVar.create(value) - assert prop.equals(expected) # type: ignore + assert prop.equals(expected) def test_create_type_error(): @@ -1133,7 +1133,7 @@ def test_var_component(): for _, imported_objects in var_data.imports ) - has_eval_react_component(ComponentVarState.field_var) # type: ignore + has_eval_react_component(ComponentVarState.field_var) # pyright: ignore [reportArgumentType] has_eval_react_component(ComponentVarState.computed_var) @@ -1145,15 +1145,15 @@ def test_type_chains(): List[int], ) assert ( - str(object_var.keys()[0].upper()) # type: ignore + str(object_var.keys()[0].upper()) == 'Object.keys(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })).at(0).toUpperCase()' ) assert ( - str(object_var.entries()[1][1] - 1) # type: ignore + str(object_var.entries()[1][1] - 1) == '(Object.entries(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })).at(1).at(1) - 1)' ) assert ( - str(object_var["c"] + object_var["b"]) # type: ignore + str(object_var["c"] + object_var["b"]) # pyright: ignore [reportCallIssue, reportOperatorIssue] == '(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["c"] + ({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["b"])' ) @@ -1162,7 +1162,7 @@ def test_nested_dict(): arr = LiteralArrayVar.create([{"bar": ["foo", "bar"]}], List[Dict[str, List[str]]]) assert ( - str(arr[0]["bar"][0]) == '[({ ["bar"] : ["foo", "bar"] })].at(0)["bar"].at(0)' + str(arr[0]["bar"][0]) == '[({ ["bar"] : ["foo", "bar"] })].at(0)["bar"].at(0)' # pyright: ignore [reportIndexIssue] ) diff --git a/tests/units/utils/test_format.py b/tests/units/utils/test_format.py index 2a2aa8259..89197a03e 100644 --- a/tests/units/utils/test_format.py +++ b/tests/units/utils/test_format.py @@ -523,7 +523,7 @@ def test_format_event_handler(input, output): input: The event handler input. output: The expected output. """ - assert format.format_event_handler(input) == output # type: ignore + assert format.format_event_handler(input) == output @pytest.mark.parametrize( @@ -582,7 +582,7 @@ formatted_router = { "input, output", [ ( - TestState(_reflex_internal_init=True).dict(), # type: ignore + TestState(_reflex_internal_init=True).dict(), # pyright: ignore [reportCallIssue] { TestState.get_full_name(): { "array": [1, 2, 3.14], @@ -615,7 +615,7 @@ formatted_router = { }, ), ( - DateTimeState(_reflex_internal_init=True).dict(), # type: ignore + DateTimeState(_reflex_internal_init=True).dict(), # pyright: ignore [reportCallIssue] { DateTimeState.get_full_name(): { "d": "1989-11-09", diff --git a/tests/units/utils/test_utils.py b/tests/units/utils/test_utils.py index 65e77f4a7..44356dac5 100644 --- a/tests/units/utils/test_utils.py +++ b/tests/units/utils/test_utils.py @@ -31,7 +31,7 @@ def get_above_max_version(): """ semantic_version_list = constants.Bun.VERSION.split(".") - semantic_version_list[-1] = str(int(semantic_version_list[-1]) + 1) # type: ignore + semantic_version_list[-1] = str(int(semantic_version_list[-1]) + 1) # pyright: ignore [reportArgumentType, reportCallIssue] return ".".join(semantic_version_list) @@ -586,9 +586,7 @@ def test_style_prop_with_event_handler_value(callable): } with pytest.raises(ReflexError): - rx.box( - style=style, # type: ignore - ) + rx.box(style=style) # pyright: ignore [reportArgumentType] def test_is_prod_mode() -> None: From 3bd2bea54d3c30e6d2a4f1613b8d0ce5070710e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Tue, 28 Jan 2025 22:47:57 +0100 Subject: [PATCH 06/13] merging two style instance should give a style instance (#4706) * merging two style instance should give a style instance * fix ci * carry _var_data --- reflex/style.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/reflex/style.py b/reflex/style.py index 5142d0181..88513dce6 100644 --- a/reflex/style.py +++ b/reflex/style.py @@ -292,6 +292,18 @@ class Style(dict): ) super().__setitem__(key, value) + def __or__(self, other: Style | dict) -> Style: + """Combine two styles. + + Args: + other: The other style to combine. + + Returns: + The combined style. + """ + _var_data = VarData.merge(self._var_data, getattr(other, "_var_data", None)) + return Style(super().__or__(self, other), _var_data=_var_data) # pyright: ignore [reportGeneralTypeIssues, reportCallIssue] + def _format_emotion_style_pseudo_selector(key: str) -> str: """Format a pseudo selector for emotion CSS-in-JS. From 2a922214a2a6d529067eea1cd21157a1a3213922 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Tue, 28 Jan 2025 16:07:53 -0800 Subject: [PATCH 07/13] improve error message for failed compile_state (#4702) --- reflex/compiler/utils.py | 8 +++++++- reflex/constants/base.py | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/reflex/compiler/utils.py b/reflex/compiler/utils.py index 02692e43b..9ccd5cb36 100644 --- a/reflex/compiler/utils.py +++ b/reflex/compiler/utils.py @@ -2,6 +2,8 @@ from __future__ import annotations +import traceback +from datetime import datetime from pathlib import Path from typing import Any, Callable, Dict, Optional, Type, Union from urllib.parse import urlparse @@ -165,8 +167,12 @@ def compile_state(state: Type[BaseState]) -> dict: try: initial_state = state(_reflex_internal_init=True).dict(initial=True) except Exception as e: + timestamp = datetime.now().strftime("%Y-%m-%d__%H-%M-%S") + constants.Reflex.LOGS_DIR.mkdir(parents=True, exist_ok=True) + log_path = constants.Reflex.LOGS_DIR / f"state_compile_error_{timestamp}.log" + traceback.TracebackException.from_exception(e).print(file=log_path.open("w+")) console.warn( - f"Failed to compile initial state with computed vars, excluding them: {e}" + f"Failed to compile initial state with computed vars. Error log saved to {log_path}" ) initial_state = state(_reflex_internal_init=True).dict( initial=True, include_computed=False diff --git a/reflex/constants/base.py b/reflex/constants/base.py index 11f3e3c05..7fbcdf18a 100644 --- a/reflex/constants/base.py +++ b/reflex/constants/base.py @@ -75,6 +75,8 @@ class Reflex(SimpleNamespace): # If user sets REFLEX_DIR envroment variable use that instead. DIR = PlatformDirs(MODULE_NAME, False).user_data_path + LOGS_DIR = DIR / "logs" + # The root directory of the reflex library. ROOT_DIR = Path(__file__).parents[2] From b8b3f8910e47db7b457f18bde7dd9f66ec04aa39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Wed, 29 Jan 2025 01:12:47 +0100 Subject: [PATCH 08/13] add more type annotations through the code (#4401) * add more type annotations through the code * add typing in reflex/utils * misc typing * more typings * state typing * keep typing * typing init and utils * more typing for components * fix attempt for 3.9 * need more __future * more typings * type event plz * type model * type vars/base.py * enable 'ANN001' for reflex folder (ignore tests and benchmarks) * fix pyi * add missing annotations * use more precise error when ignoring --- pyproject.toml | 6 +- reflex/__init__.py | 5 +- reflex/app.py | 35 ++++++------ reflex/app_mixins/lifespan.py | 2 +- reflex/base.py | 2 +- reflex/compiler/utils.py | 2 +- reflex/components/component.py | 10 ++-- reflex/components/core/client_side_routing.py | 2 +- .../components/core/client_side_routing.pyi | 2 +- reflex/components/core/cond.py | 2 +- reflex/components/core/match.py | 2 +- reflex/components/datadisplay/logo.py | 6 +- reflex/components/el/element.py | 2 +- reflex/components/markdown/markdown.py | 8 ++- reflex/components/next/image.py | 4 +- reflex/components/props.py | 2 +- reflex/components/radix/themes/color_mode.py | 12 ++-- reflex/components/radix/themes/layout/list.py | 2 +- reflex/components/recharts/charts.py | 2 +- reflex/components/sonner/toast.py | 20 +++---- reflex/components/sonner/toast.pyi | 10 ++-- reflex/components/suneditor/editor.py | 10 ++-- reflex/components/suneditor/editor.pyi | 4 +- reflex/components/tags/tag.py | 2 +- reflex/config.py | 6 +- reflex/custom_components/custom_components.py | 2 +- reflex/event.py | 13 +++-- reflex/experimental/hooks.py | 10 ++-- reflex/experimental/misc.py | 6 +- reflex/istate/wrappers.py | 2 +- reflex/model.py | 13 +++-- reflex/page.py | 6 +- reflex/reflex.py | 20 ++++--- reflex/route.py | 2 +- reflex/state.py | 53 ++++++++++-------- reflex/style.py | 4 +- reflex/testing.py | 6 +- reflex/utils/build.py | 2 +- reflex/utils/compat.py | 3 +- reflex/utils/exceptions.py | 4 +- reflex/utils/exec.py | 16 +++--- reflex/utils/format.py | 4 +- reflex/utils/lazy_loader.py | 8 ++- reflex/utils/prerequisites.py | 16 ++++-- reflex/utils/processes.py | 39 +++++++------ reflex/utils/pyi_generator.py | 14 +++-- reflex/utils/registry.py | 8 +-- reflex/utils/telemetry.py | 4 +- reflex/utils/types.py | 8 +-- reflex/vars/base.py | 56 ++++++++++++------- reflex/vars/function.py | 4 ++ reflex/vars/object.py | 2 +- reflex/vars/sequence.py | 9 ++- scripts/wait_for_listening_port.py | 4 +- 54 files changed, 285 insertions(+), 213 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 761f9e2c9..6eeb17489 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -86,14 +86,14 @@ reportIncompatibleMethodOverride = false target-version = "py310" output-format = "concise" lint.isort.split-on-trailing-comma = false -lint.select = ["B", "C4", "D", "E", "ERA", "F", "FURB", "I", "N", "PERF", "PGH", "PTH", "RUF", "SIM", "T", "TRY", "W"] +lint.select = ["ANN001","B", "C4", "D", "E", "ERA", "F", "FURB", "I", "N", "PERF", "PGH", "PTH", "RUF", "SIM", "T", "TRY", "W"] lint.ignore = ["B008", "D205", "E501", "F403", "SIM115", "RUF006", "RUF012", "TRY0"] lint.pydocstyle.convention = "google" [tool.ruff.lint.per-file-ignores] "__init__.py" = ["F401"] -"tests/*.py" = ["D100", "D103", "D104", "B018", "PERF", "T", "N"] -"benchmarks/*.py" = ["D100", "D103", "D104", "B018", "PERF", "T", "N"] +"tests/*.py" = ["ANN001", "D100", "D103", "D104", "B018", "PERF", "T", "N"] +"benchmarks/*.py" = ["ANN001", "D100", "D103", "D104", "B018", "PERF", "T", "N"] "reflex/.templates/*.py" = ["D100", "D103", "D104"] "*.pyi" = ["D301", "D415", "D417", "D418", "E742", "N", "PGH"] "pyi_generator.py" = ["N802"] diff --git a/reflex/__init__.py b/reflex/__init__.py index 72089aca0..3209b505e 100644 --- a/reflex/__init__.py +++ b/reflex/__init__.py @@ -84,6 +84,9 @@ In the example above, you will be able to do `rx.list` from __future__ import annotations +from types import ModuleType +from typing import Any + from reflex.utils import ( compat, # for side-effects lazy_loader, @@ -365,5 +368,5 @@ getattr, __dir__, __all__ = lazy_loader.attach( ) -def __getattr__(name): +def __getattr__(name: ModuleType | Any): return getattr(name) diff --git a/reflex/app.py b/reflex/app.py index e3b45e7b2..9fe0f2992 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -408,15 +408,15 @@ class App(MiddlewareMixin, LifespanMixin): if self.api: class HeaderMiddleware: - def __init__(self, app): + def __init__(self, app: ASGIApp): self.app = app async def __call__( - self, scope: MutableMapping[str, Any], receive, send + self, scope: MutableMapping[str, Any], receive: Any, send: Callable ): original_send = send - async def modified_send(message): + async def modified_send(message: dict): if message["type"] == "websocket.accept": if scope.get("subprotocols"): # The following *does* say "subprotocol" instead of "subprotocols", intentionally. @@ -712,8 +712,8 @@ class App(MiddlewareMixin, LifespanMixin): Args: component: The component to display at the page. title: The title of the page. - description: The description of the page. image: The image to display on the page. + description: The description of the page. on_load: The event handler(s) that will be called each time the page load. meta: The metadata of the page. """ @@ -1056,7 +1056,7 @@ class App(MiddlewareMixin, LifespanMixin): with executor: result_futures = [] - def _submit_work(fn, *args, **kwargs): + def _submit_work(fn: Callable, *args, **kwargs): f = executor.submit(fn, *args, **kwargs) result_futures.append(f) @@ -1387,15 +1387,14 @@ async def process( if app._process_background(state, event) is not None: # `final=True` allows the frontend send more events immediately. yield StateUpdate(final=True) - return + else: + # Process the event synchronously. + async for update in state._process(event): + # Postprocess the event. + update = await app._postprocess(state, event, update) - # Process the event synchronously. - async for update in state._process(event): - # Postprocess the event. - update = await app._postprocess(state, event, update) - - # Yield the update. - yield update + # Yield the update. + yield update except Exception as ex: telemetry.send_error(ex, context="backend") @@ -1590,20 +1589,20 @@ class EventNamespace(AsyncNamespace): self.sid_to_token = {} self.app = app - def on_connect(self, sid, environ): + def on_connect(self, sid: str, environ: dict): """Event for when the websocket is connected. Args: sid: The Socket.IO session id. environ: The request information, including HTTP headers. """ - subprotocol = environ.get("HTTP_SEC_WEBSOCKET_PROTOCOL", None) + subprotocol = environ.get("HTTP_SEC_WEBSOCKET_PROTOCOL") if subprotocol and subprotocol != constants.Reflex.VERSION: console.warn( f"Frontend version {subprotocol} for session {sid} does not match the backend version {constants.Reflex.VERSION}." ) - def on_disconnect(self, sid): + def on_disconnect(self, sid: str): """Event for when the websocket disconnects. Args: @@ -1625,7 +1624,7 @@ class EventNamespace(AsyncNamespace): self.emit(str(constants.SocketEvent.EVENT), update, to=sid) ) - async def on_event(self, sid, data): + async def on_event(self, sid: str, data: Any): """Event for receiving front-end websocket events. Raises: @@ -1692,7 +1691,7 @@ class EventNamespace(AsyncNamespace): # Emit the update from processing the event. await self.emit_update(update=update, sid=sid) - async def on_ping(self, sid): + async def on_ping(self, sid: str): """Event for testing the API endpoint. Args: diff --git a/reflex/app_mixins/lifespan.py b/reflex/app_mixins/lifespan.py index 8bdef2eb9..50b90f25c 100644 --- a/reflex/app_mixins/lifespan.py +++ b/reflex/app_mixins/lifespan.py @@ -61,7 +61,7 @@ class LifespanMixin(AppMixin): Args: task: The task to register. - task_kwargs: The kwargs of the task. + **task_kwargs: The kwargs of the task. Raises: InvalidLifespanTaskTypeError: If the task is a generator function. diff --git a/reflex/base.py b/reflex/base.py index 5c0180812..f6bbb8ce4 100644 --- a/reflex/base.py +++ b/reflex/base.py @@ -80,7 +80,7 @@ class Base(BaseModel): # pyright: ignore [reportPossiblyUnboundVariable] default=serialize, ) - def set(self, **kwargs): + def set(self, **kwargs: Any): """Set multiple fields and return the object. Args: diff --git a/reflex/compiler/utils.py b/reflex/compiler/utils.py index 9ccd5cb36..d145e6c0b 100644 --- a/reflex/compiler/utils.py +++ b/reflex/compiler/utils.py @@ -502,7 +502,7 @@ def empty_dir(path: str | Path, keep_files: list[str] | None = None): path_ops.rm(element) -def is_valid_url(url) -> bool: +def is_valid_url(url: str) -> bool: """Check if a url is valid. Args: diff --git a/reflex/components/component.py b/reflex/components/component.py index c88330918..3f1b88fea 100644 --- a/reflex/components/component.py +++ b/reflex/components/component.py @@ -426,7 +426,7 @@ class Component(BaseComponent, ABC): else: continue - def determine_key(value): + def determine_key(value: Any): # Try to create a var from the value key = value if isinstance(value, Var) else LiteralVar.create(value) @@ -707,7 +707,7 @@ class Component(BaseComponent, ABC): # Filter out None props props = {key: value for key, value in props.items() if value is not None} - def validate_children(children): + def validate_children(children: tuple | list): for child in children: if isinstance(child, (tuple, list)): validate_children(child) @@ -851,7 +851,7 @@ class Component(BaseComponent, ABC): else {} ) - def render(self) -> Dict: + def render(self) -> dict: """Render the component. Returns: @@ -869,7 +869,7 @@ class Component(BaseComponent, ABC): self._replace_prop_names(rendered_dict) return rendered_dict - def _replace_prop_names(self, rendered_dict) -> None: + def _replace_prop_names(self, rendered_dict: dict) -> None: """Replace the prop names in the render dictionary. Args: @@ -909,7 +909,7 @@ class Component(BaseComponent, ABC): comp.__name__ for comp in (Fragment, Foreach, Cond, Match) ] - def validate_child(child): + def validate_child(child: Any): child_name = type(child).__name__ # Iterate through the immediate children of fragment diff --git a/reflex/components/core/client_side_routing.py b/reflex/components/core/client_side_routing.py index a10b90de8..0fc40de5f 100644 --- a/reflex/components/core/client_side_routing.py +++ b/reflex/components/core/client_side_routing.py @@ -41,7 +41,7 @@ class ClientSideRouting(Component): return "" -def wait_for_client_redirect(component) -> Component: +def wait_for_client_redirect(component: Component) -> Component: """Wait for a redirect to occur before rendering a component. This prevents the 404 page from flashing while the redirect is happening. diff --git a/reflex/components/core/client_side_routing.pyi b/reflex/components/core/client_side_routing.pyi index 581b0e120..078698198 100644 --- a/reflex/components/core/client_side_routing.pyi +++ b/reflex/components/core/client_side_routing.pyi @@ -60,7 +60,7 @@ class ClientSideRouting(Component): """ ... -def wait_for_client_redirect(component) -> Component: ... +def wait_for_client_redirect(component: Component) -> Component: ... class Default404Page(Component): @overload diff --git a/reflex/components/core/cond.py b/reflex/components/core/cond.py index 25b691808..6f9110a16 100644 --- a/reflex/components/core/cond.py +++ b/reflex/components/core/cond.py @@ -153,7 +153,7 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | Var: if c2 is None: raise ValueError("For conditional vars, the second argument must be set.") - def create_var(cond_part): + def create_var(cond_part: Any) -> Var[Any]: return LiteralVar.create(cond_part) # convert the truth and false cond parts into vars so the _var_data can be obtained. diff --git a/reflex/components/core/match.py b/reflex/components/core/match.py index ae8568ac5..5c31669a1 100644 --- a/reflex/components/core/match.py +++ b/reflex/components/core/match.py @@ -109,7 +109,7 @@ class Match(MemoizationLeaf): return cases, default @classmethod - def _create_case_var_with_var_data(cls, case_element): + def _create_case_var_with_var_data(cls, case_element: Any) -> Var: """Convert a case element into a Var.If the case is a Style type, we extract the var data and merge it with the newly created Var. diff --git a/reflex/components/datadisplay/logo.py b/reflex/components/datadisplay/logo.py index d960b8cee..1c4c02001 100644 --- a/reflex/components/datadisplay/logo.py +++ b/reflex/components/datadisplay/logo.py @@ -15,10 +15,8 @@ def svg_logo(color: Union[str, rx.Var[str]] = rx.color_mode_cond("#110F1F", "whi The Reflex logo SVG. """ - def logo_path(d): - return rx.el.svg.path( - d=d, - ) + def logo_path(d: str): + return rx.el.svg.path(d=d) paths = [ "M0 11.5999V0.399902H8.96V4.8799H6.72V2.6399H2.24V4.8799H6.72V7.1199H2.24V11.5999H0ZM6.72 11.5999V7.1199H8.96V11.5999H6.72Z", diff --git a/reflex/components/el/element.py b/reflex/components/el/element.py index 213cea65a..c9a58b1f6 100644 --- a/reflex/components/el/element.py +++ b/reflex/components/el/element.py @@ -6,7 +6,7 @@ from reflex.components.component import Component class Element(Component): """The base class for all raw HTML elements.""" - def __eq__(self, other): + def __eq__(self, other: object): """Two elements are equal if they have the same tag. Args: diff --git a/reflex/components/markdown/markdown.py b/reflex/components/markdown/markdown.py index 686c49a64..27bd5bd62 100644 --- a/reflex/components/markdown/markdown.py +++ b/reflex/components/markdown/markdown.py @@ -8,7 +8,7 @@ from functools import lru_cache from hashlib import md5 from typing import Any, Callable, Dict, Sequence, Union -from reflex.components.component import Component, CustomComponent +from reflex.components.component import BaseComponent, Component, CustomComponent from reflex.components.tags.tag import Tag from reflex.utils import types from reflex.utils.imports import ImportDict, ImportVar @@ -379,7 +379,9 @@ const {_LANGUAGE!s} = match ? match[1] : ''; # fallback to the default fn Var creation if the component is not a MarkdownComponentMap. return MarkdownComponentMap.create_map_fn_var(fn_body=formatted_component) - def _get_map_fn_custom_code_from_children(self, component) -> list[str]: + def _get_map_fn_custom_code_from_children( + self, component: BaseComponent + ) -> list[str]: """Recursively get markdown custom code from children components. Args: @@ -409,7 +411,7 @@ const {_LANGUAGE!s} = match ? match[1] : ''; return custom_code_list @staticmethod - def _component_map_hash(component_map) -> str: + def _component_map_hash(component_map: dict) -> str: inp = str( {tag: component(_MOCK_ARG) for tag, component in component_map.items()} ).encode() diff --git a/reflex/components/next/image.py b/reflex/components/next/image.py index 00821ddaf..20ba5a304 100644 --- a/reflex/components/next/image.py +++ b/reflex/components/next/image.py @@ -1,5 +1,7 @@ """Image component from next/image.""" +from __future__ import annotations + from typing import Any, Literal, Optional, Union from reflex.event import EventHandler, no_args_event_spec @@ -93,7 +95,7 @@ class Image(NextComponent): style = props.get("style", {}) - def check_prop_type(prop_name, prop_value): + def check_prop_type(prop_name: str, prop_value: int | str | None): if types.check_prop_in_allowed_types(prop_value, allowed_types=[int]): props[prop_name] = prop_value diff --git a/reflex/components/props.py b/reflex/components/props.py index 823036406..779e714d9 100644 --- a/reflex/components/props.py +++ b/reflex/components/props.py @@ -48,7 +48,7 @@ class PropsBase(Base): class NoExtrasAllowedProps(Base): """A class that holds props to be passed or applied to a component with no extra props allowed.""" - def __init__(self, component_name=None, **kwargs): + def __init__(self, component_name: str | None = None, **kwargs): """Initialize the props. Args: diff --git a/reflex/components/radix/themes/color_mode.py b/reflex/components/radix/themes/color_mode.py index 2377a2422..d9b7c0b02 100644 --- a/reflex/components/radix/themes/color_mode.py +++ b/reflex/components/radix/themes/color_mode.py @@ -17,7 +17,7 @@ rx.text( from __future__ import annotations -from typing import Dict, List, Literal, Optional, Union, get_args +from typing import Any, Dict, List, Literal, Optional, Union, get_args from reflex.components.component import BaseComponent from reflex.components.core.cond import Cond, color_mode_cond, cond @@ -78,17 +78,19 @@ position_map: Dict[str, List[str]] = { # needed to inverse contains for find -def _find(const: List[str], var): +def _find(const: List[str], var: Any): return LiteralArrayVar.create(const).contains(var) -def _set_var_default(props, position, prop, default1, default2=""): +def _set_var_default( + props: dict, position: Any, prop: str, default1: str, default2: str = "" +): props.setdefault( prop, cond(_find(position_map[prop], position), default1, default2) ) -def _set_static_default(props, position, prop, default): +def _set_static_default(props: dict, position: Any, prop: str, default: str): if prop in position: props.setdefault(prop, default) @@ -142,7 +144,7 @@ class ColorModeIconButton(IconButton): if allow_system: - def color_mode_item(_color_mode): + def color_mode_item(_color_mode: str): return dropdown_menu.item( _color_mode.title(), on_click=set_color_mode(_color_mode) ) diff --git a/reflex/components/radix/themes/layout/list.py b/reflex/components/radix/themes/layout/list.py index b79e99bf7..04fcb6ae5 100644 --- a/reflex/components/radix/themes/layout/list.py +++ b/reflex/components/radix/themes/layout/list.py @@ -189,7 +189,7 @@ ordered_list = list_ns.ordered unordered_list = list_ns.unordered -def __getattr__(name): +def __getattr__(name: Any): # special case for when accessing list to avoid shadowing # python's built in list object. if name == "list": diff --git a/reflex/components/recharts/charts.py b/reflex/components/recharts/charts.py index 6edfce58f..3e9df4143 100644 --- a/reflex/components/recharts/charts.py +++ b/reflex/components/recharts/charts.py @@ -69,7 +69,7 @@ class ChartBase(RechartsCharts): ) @classmethod - def create(cls, *children, **props) -> Component: + def create(cls, *children: Any, **props: Any) -> Component: """Create a chart component. Args: diff --git a/reflex/components/sonner/toast.py b/reflex/components/sonner/toast.py index 0f666fd64..dbac8e733 100644 --- a/reflex/components/sonner/toast.py +++ b/reflex/components/sonner/toast.py @@ -132,7 +132,7 @@ class ToastProps(PropsBase, NoExtrasAllowedProps): # Function that gets called when the toast disappears automatically after it's timeout (duration` prop). on_auto_close: Optional[Any] - def dict(self, *args, **kwargs) -> dict[str, Any]: + def dict(self, *args: Any, **kwargs: Any) -> dict[str, Any]: """Convert the object to a dictionary. Args: @@ -276,12 +276,12 @@ class Toaster(Component): return run_script(toast) @staticmethod - def toast_info(message: str | Var = "", **kwargs): + def toast_info(message: str | Var = "", **kwargs: Any): """Display an info toast message. Args: message: The message to display. - kwargs: Additional toast props. + **kwargs: Additional toast props. Returns: The toast event. @@ -289,12 +289,12 @@ class Toaster(Component): return Toaster.send_toast(message, level="info", **kwargs) @staticmethod - def toast_warning(message: str | Var = "", **kwargs): + def toast_warning(message: str | Var = "", **kwargs: Any): """Display a warning toast message. Args: message: The message to display. - kwargs: Additional toast props. + **kwargs: Additional toast props. Returns: The toast event. @@ -302,12 +302,12 @@ class Toaster(Component): return Toaster.send_toast(message, level="warning", **kwargs) @staticmethod - def toast_error(message: str | Var = "", **kwargs): + def toast_error(message: str | Var = "", **kwargs: Any): """Display an error toast message. Args: message: The message to display. - kwargs: Additional toast props. + **kwargs: Additional toast props. Returns: The toast event. @@ -315,12 +315,12 @@ class Toaster(Component): return Toaster.send_toast(message, level="error", **kwargs) @staticmethod - def toast_success(message: str | Var = "", **kwargs): + def toast_success(message: str | Var = "", **kwargs: Any): """Display a success toast message. Args: message: The message to display. - kwargs: Additional toast props. + **kwargs: Additional toast props. Returns: The toast event. @@ -352,7 +352,7 @@ class Toaster(Component): return run_script(dismiss_action) @classmethod - def create(cls, *children, **props) -> Component: + def create(cls, *children: Any, **props: Any) -> Component: """Create a toaster component. Args: diff --git a/reflex/components/sonner/toast.pyi b/reflex/components/sonner/toast.pyi index 7fd9fdf54..829e959d5 100644 --- a/reflex/components/sonner/toast.pyi +++ b/reflex/components/sonner/toast.pyi @@ -51,7 +51,7 @@ class ToastProps(PropsBase, NoExtrasAllowedProps): on_dismiss: Optional[Any] on_auto_close: Optional[Any] - def dict(self, *args, **kwargs) -> dict[str, Any]: ... + def dict(self, *args: Any, **kwargs: Any) -> dict[str, Any]: ... class Toaster(Component): is_used: ClassVar[bool] = False @@ -62,13 +62,13 @@ class Toaster(Component): message: str | Var = "", level: str | None = None, **props ) -> EventSpec: ... @staticmethod - def toast_info(message: str | Var = "", **kwargs): ... + def toast_info(message: str | Var = "", **kwargs: Any): ... @staticmethod - def toast_warning(message: str | Var = "", **kwargs): ... + def toast_warning(message: str | Var = "", **kwargs: Any): ... @staticmethod - def toast_error(message: str | Var = "", **kwargs): ... + def toast_error(message: str | Var = "", **kwargs: Any): ... @staticmethod - def toast_success(message: str | Var = "", **kwargs): ... + def toast_success(message: str | Var = "", **kwargs: Any): ... @staticmethod def toast_dismiss(id: Var | str | None = None): ... @overload diff --git a/reflex/components/suneditor/editor.py b/reflex/components/suneditor/editor.py index d40f0e9ad..3edf27545 100644 --- a/reflex/components/suneditor/editor.py +++ b/reflex/components/suneditor/editor.py @@ -3,7 +3,7 @@ from __future__ import annotations import enum -from typing import Dict, List, Literal, Optional, Tuple, Union +from typing import Any, Dict, List, Literal, Optional, Tuple, Union from reflex.base import Base from reflex.components.component import Component, NoSSRComponent @@ -115,7 +115,7 @@ class Editor(NoSSRComponent): # Alternatively to a string, a dict of your language can be passed to this prop. # Please refer to the library docs for this. # options: "en" | "da" | "de" | "es" | "fr" | "ja" | "ko" | "pt_br" | - # "ru" | "zh_cn" | "ro" | "pl" | "ckb" | "lv" | "se" | "ua" | "he" | "it" + # "ru" | "zh_cn" | "ro" | "pl" | "ckb" | "lv" | "se" | "ua" | "he" | "it" # default: "en". lang: Var[ Union[ @@ -244,11 +244,13 @@ class Editor(NoSSRComponent): } @classmethod - def create(cls, set_options: Optional[EditorOptions] = None, **props) -> Component: + def create( + cls, set_options: Optional[EditorOptions] = None, **props: Any + ) -> Component: """Create an instance of Editor. No children allowed. Args: - set_options(Optional[EditorOptions]): Configuration object to further configure the instance. + set_options: Configuration object to further configure the instance. **props: Any properties to be passed to the Editor Returns: diff --git a/reflex/components/suneditor/editor.pyi b/reflex/components/suneditor/editor.pyi index b52fd43da..5577220cb 100644 --- a/reflex/components/suneditor/editor.pyi +++ b/reflex/components/suneditor/editor.pyi @@ -171,8 +171,8 @@ class Editor(NoSSRComponent): """Create an instance of Editor. No children allowed. Args: - set_options(Optional[EditorOptions]): Configuration object to further configure the instance. - lang: Language of the editor. Alternatively to a string, a dict of your language can be passed to this prop. Please refer to the library docs for this. options: "en" | "da" | "de" | "es" | "fr" | "ja" | "ko" | "pt_br" | "ru" | "zh_cn" | "ro" | "pl" | "ckb" | "lv" | "se" | "ua" | "he" | "it" default: "en". + set_options: Configuration object to further configure the instance. + lang: Language of the editor. Alternatively to a string, a dict of your language can be passed to this prop. Please refer to the library docs for this. options: "en" | "da" | "de" | "es" | "fr" | "ja" | "ko" | "pt_br" | "ru" | "zh_cn" | "ro" | "pl" | "ckb" | "lv" | "se" | "ua" | "he" | "it" default: "en". name: This is used to set the HTML form name of the editor. This means on HTML form submission, it will be submitted together with contents of the editor by the name provided. default_value: Sets the default value of the editor. This is useful if you don't want the on_change method to be called on render. If you want the on_change method to be called on render please use the set_contents prop width: Sets the width of the editor. px and percentage values are accepted, eg width="100%" or width="500px" default: 100% diff --git a/reflex/components/tags/tag.py b/reflex/components/tags/tag.py index 0587c61ed..8569d5d50 100644 --- a/reflex/components/tags/tag.py +++ b/reflex/components/tags/tag.py @@ -49,7 +49,7 @@ class Tag: """Set the tag's fields. Args: - kwargs: The fields to set. + **kwargs: The fields to set. Returns: The tag with the fields diff --git a/reflex/config.py b/reflex/config.py index a76bf987d..f6992f8b5 100644 --- a/reflex/config.py +++ b/reflex/config.py @@ -407,7 +407,7 @@ class env_var: # noqa: N801 # pyright: ignore [reportRedeclaration] self.default = default self.internal = internal - def __set_name__(self, owner, name): + def __set_name__(self, owner: Any, name: str): """Set the name of the descriptor. Args: @@ -416,7 +416,7 @@ class env_var: # noqa: N801 # pyright: ignore [reportRedeclaration] """ self.name = name - def __get__(self, instance, owner): + def __get__(self, instance: Any, owner: Any): """Get the EnvVar instance. Args: @@ -435,7 +435,7 @@ class env_var: # noqa: N801 # pyright: ignore [reportRedeclaration] if TYPE_CHECKING: - def env_var(default, internal=False) -> EnvVar: + def env_var(default: Any, internal: bool = False) -> EnvVar: """Typing helper for the env_var descriptor. Args: diff --git a/reflex/custom_components/custom_components.py b/reflex/custom_components/custom_components.py index 3bfbb1580..024e77eee 100644 --- a/reflex/custom_components/custom_components.py +++ b/reflex/custom_components/custom_components.py @@ -83,7 +83,7 @@ def _get_package_config(exit_on_fail: bool = True) -> dict: The package configuration. Raises: - Exit: If the pyproject.toml file is not found. + Exit: If the pyproject.toml file is not found and exit_on_fail is True. """ pyproject = Path(CustomComponents.PYPROJECT_TOML) try: diff --git a/reflex/event.py b/reflex/event.py index 0fc874b38..fbbfc70b2 100644 --- a/reflex/event.py +++ b/reflex/event.py @@ -1075,7 +1075,8 @@ def download( ) -def _callback_arg_spec(eval_result): +# This function seems unused. Check if we still need it. If not, remove in 0.7.0 +def _callback_arg_spec(eval_result: Any): """ArgSpec for call_script callback function. Args: @@ -1180,7 +1181,7 @@ def run_script( return call_function(ArgsFunctionOperation.create((), javascript_code), callback) -def get_event(state, event): +def get_event(state: BaseState, event: str): """Get the event from the given state. Args: @@ -1193,7 +1194,7 @@ def get_event(state, event): return f"{state.get_name()}.{event}" -def get_hydrate_event(state) -> str: +def get_hydrate_event(state: BaseState) -> str: """Get the name of the hydrate event for the state. Args: @@ -1832,13 +1833,13 @@ class EventCallback(Generic[P, T]): @overload def __get__( - self: EventCallback[P, T], instance: None, owner + self: EventCallback[P, T], instance: None, owner: Any ) -> EventCallback[P, T]: ... @overload - def __get__(self, instance, owner) -> Callable[P, T]: ... + def __get__(self, instance: Any, owner: Any) -> Callable[P, T]: ... - def __get__(self, instance, owner) -> Callable: + def __get__(self, instance: Any, owner: Any) -> Callable: """Get the function with the instance bound to it. Args: diff --git a/reflex/experimental/hooks.py b/reflex/experimental/hooks.py index e0d3b4a56..c00dd3bf9 100644 --- a/reflex/experimental/hooks.py +++ b/reflex/experimental/hooks.py @@ -11,7 +11,7 @@ def _compose_react_imports(tags: list[str]) -> dict[str, list[ImportVar]]: return {"react": [ImportVar(tag=tag) for tag in tags]} -def const(name, value) -> Var: +def const(name: str | list[str], value: str | Var) -> Var: """Create a constant Var. Args: @@ -26,7 +26,7 @@ def const(name, value) -> Var: return Var(_js_expr=f"const {name} = {value}") -def useCallback(func, deps) -> Var: # noqa: N802 +def useCallback(func: str, deps: list) -> Var: # noqa: N802 """Create a useCallback hook with a function and dependencies. Args: @@ -42,7 +42,7 @@ def useCallback(func, deps) -> Var: # noqa: N802 ) -def useContext(context) -> Var: # noqa: N802 +def useContext(context: str) -> Var: # noqa: N802 """Create a useContext hook with a context. Args: @@ -57,7 +57,7 @@ def useContext(context) -> Var: # noqa: N802 ) -def useRef(default) -> Var: # noqa: N802 +def useRef(default: str) -> Var: # noqa: N802 """Create a useRef hook with a default value. Args: @@ -72,7 +72,7 @@ def useRef(default) -> Var: # noqa: N802 ) -def useState(var_name, default=None) -> Var: # noqa: N802 +def useState(var_name: str, default: str | None = None) -> Var: # noqa: N802 """Create a useState hook with a variable name and setter name. Args: diff --git a/reflex/experimental/misc.py b/reflex/experimental/misc.py index a2a5a0615..986729881 100644 --- a/reflex/experimental/misc.py +++ b/reflex/experimental/misc.py @@ -1,16 +1,16 @@ """Miscellaneous functions for the experimental package.""" import asyncio -from typing import Any +from typing import Any, Callable -async def run_in_thread(func) -> Any: +async def run_in_thread(func: Callable) -> Any: """Run a function in a separate thread. To not block the UI event queue, run_in_thread must be inside inside a rx.event(background=True) decorated method. Args: - func (callable): The non-async function to run. + func: The non-async function to run. Raises: ValueError: If the function is an async function. diff --git a/reflex/istate/wrappers.py b/reflex/istate/wrappers.py index d4e74cf8a..865bd6c63 100644 --- a/reflex/istate/wrappers.py +++ b/reflex/istate/wrappers.py @@ -6,7 +6,7 @@ from reflex.istate.proxy import ReadOnlyStateProxy from reflex.state import _split_substate_key, _substate_key, get_state_manager -async def get_state(token, state_cls: Any | None = None) -> ReadOnlyStateProxy: +async def get_state(token: str, state_cls: Any | None = None) -> ReadOnlyStateProxy: """Get the instance of a state for a token. Args: diff --git a/reflex/model.py b/reflex/model.py index 6e44498e9..06bb87b02 100644 --- a/reflex/model.py +++ b/reflex/model.py @@ -18,6 +18,7 @@ import sqlalchemy import sqlalchemy.exc import sqlalchemy.ext.asyncio import sqlalchemy.orm +from alembic.runtime.migration import MigrationContext from reflex.base import Base from reflex.config import environment, get_config @@ -261,7 +262,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue super().__init_subclass__() @classmethod - def _dict_recursive(cls, value): + def _dict_recursive(cls, value: Any): """Recursively serialize the relationship object(s). Args: @@ -393,7 +394,11 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue writer = alembic.autogenerate.rewriter.Rewriter() @writer.rewrites(alembic.operations.ops.AddColumnOp) - def render_add_column_with_server_default(context, revision, op): + def render_add_column_with_server_default( + context: MigrationContext, + revision: str | None, + op: Any, + ): # Carry the sqlmodel default as server_default so that newly added # columns get the desired default value in existing rows. if op.column.default is not None and op.column.server_default is None: @@ -402,7 +407,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue ) return op - def run_autogenerate(rev, context): + def run_autogenerate(rev: str, context: MigrationContext): revision_context.run_autogenerate(rev, context) return [] @@ -444,7 +449,7 @@ class Model(Base, sqlmodel.SQLModel): # pyright: ignore [reportGeneralTypeIssue """ config, script_directory = cls._alembic_config() - def run_upgrade(rev, context): + def run_upgrade(rev: str, context: MigrationContext): return script_directory._upgrade_revs(to_rev, rev) with alembic.runtime.environment.EnvironmentContext( diff --git a/reflex/page.py b/reflex/page.py index 44ca6ab31..5f118aad1 100644 --- a/reflex/page.py +++ b/reflex/page.py @@ -3,7 +3,7 @@ from __future__ import annotations from collections import defaultdict -from typing import Any, Dict, List +from typing import Any, Callable, Dict, List from reflex.config import get_config from reflex.event import BASE_STATE, EventType @@ -42,7 +42,7 @@ def page( The decorated function. """ - def decorator(render_fn): + def decorator(render_fn: Callable): kwargs = {} if route: kwargs["route"] = route @@ -66,7 +66,7 @@ def page( return decorator -def get_decorated_pages(omit_implicit_routes=True) -> list[dict[str, Any]]: +def get_decorated_pages(omit_implicit_routes: bool = True) -> list[dict[str, Any]]: """Get the decorated pages. Args: diff --git a/reflex/reflex.py b/reflex/reflex.py index 2fb10a944..d1e565665 100644 --- a/reflex/reflex.py +++ b/reflex/reflex.py @@ -125,8 +125,8 @@ def _run( env: constants.Env = constants.Env.DEV, frontend: bool = True, backend: bool = True, - frontend_port: str = str(config.frontend_port), - backend_port: str = str(config.backend_port), + frontend_port: int = config.frontend_port, + backend_port: int = config.backend_port, backend_host: str = config.backend_host, loglevel: constants.LogLevel = config.loglevel, ): @@ -160,18 +160,22 @@ def _run( # Find the next available open port if applicable. if frontend: frontend_port = processes.handle_port( - "frontend", frontend_port, str(constants.DefaultPorts.FRONTEND_PORT) + "frontend", + frontend_port, + constants.DefaultPorts.FRONTEND_PORT, ) if backend: backend_port = processes.handle_port( - "backend", backend_port, str(constants.DefaultPorts.BACKEND_PORT) + "backend", + backend_port, + constants.DefaultPorts.BACKEND_PORT, ) # Apply the new ports to the config. - if frontend_port != str(config.frontend_port): + if frontend_port != config.frontend_port: config._set_persistent(frontend_port=frontend_port) - if backend_port != str(config.backend_port): + if backend_port != config.backend_port: config._set_persistent(backend_port=backend_port) # Reload the config to make sure the env vars are persistent. @@ -262,10 +266,10 @@ def run( help="Execute only backend.", envvar=environment.REFLEX_BACKEND_ONLY.name, ), - frontend_port: str = typer.Option( + frontend_port: int = typer.Option( config.frontend_port, help="Specify a different frontend port." ), - backend_port: str = typer.Option( + backend_port: int = typer.Option( config.backend_port, help="Specify a different backend port." ), backend_host: str = typer.Option( diff --git a/reflex/route.py b/reflex/route.py index 0b7172824..3f49f66e9 100644 --- a/reflex/route.py +++ b/reflex/route.py @@ -103,7 +103,7 @@ def catchall_prefix(route: str) -> str: return route.replace(pattern, "") if pattern else "" -def replace_brackets_with_keywords(input_string): +def replace_brackets_with_keywords(input_string: str) -> str: """Replace brackets and everything inside it in a string with a keyword. Args: diff --git a/reflex/state.py b/reflex/state.py index badc40dfd..a0b91c94f 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -31,6 +31,7 @@ from typing import ( Optional, Sequence, Set, + SupportsIndex, Tuple, Type, TypeVar, @@ -1058,7 +1059,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): setattr(cls, prop._var_field_name, prop) @classmethod - def _create_event_handler(cls, fn): + def _create_event_handler(cls, fn: Any): """Create an event handler for the given function. Args: @@ -1176,14 +1177,14 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): cls._check_overwritten_dynamic_args(list(args.keys())) - def argsingle_factory(param): - def inner_func(self) -> str: + def argsingle_factory(param: str): + def inner_func(self: BaseState) -> str: return self.router.page.params.get(param, "") return inner_func - def arglist_factory(param): - def inner_func(self) -> List[str]: + def arglist_factory(param: str): + def inner_func(self: BaseState) -> List[str]: return self.router.page.params.get(param, []) return inner_func @@ -2594,7 +2595,9 @@ class StateProxy(wrapt.ObjectProxy): """ def __init__( - self, state_instance, parent_state_proxy: Optional["StateProxy"] = None + self, + state_instance: BaseState, + parent_state_proxy: Optional["StateProxy"] = None, ): """Create a proxy for a state instance. @@ -3540,7 +3543,9 @@ class StateManagerRedis(StateManager): @validator("lock_warning_threshold") @classmethod - def validate_lock_warning_threshold(cls, lock_warning_threshold: int, values): + def validate_lock_warning_threshold( + cls, lock_warning_threshold: int, values: dict[str, int] + ): """Validate the lock warning threshold. Args: @@ -3808,10 +3813,10 @@ class MutableProxy(wrapt.ObjectProxy): def _mark_dirty( self, - wrapped=None, - instance=None, - args=(), - kwargs=None, + wrapped: Callable | None = None, + instance: BaseState | None = None, + args: tuple = (), + kwargs: dict | None = None, ) -> Any: """Mark the state as dirty, then call a wrapped function. @@ -3885,7 +3890,9 @@ class MutableProxy(wrapt.ObjectProxy): ) return value - def _wrap_recursive_decorator(self, wrapped, instance, args, kwargs) -> Any: + def _wrap_recursive_decorator( + self, wrapped: Callable, instance: BaseState, args: list, kwargs: dict + ) -> Any: """Wrap a function that returns a possibly mutable value. Intended for use with `FunctionWrapper` from the `wrapt` library. @@ -3944,7 +3951,7 @@ class MutableProxy(wrapt.ObjectProxy): return value - def __getitem__(self, key) -> Any: + def __getitem__(self, key: Any) -> Any: """Get the item on the proxied object and return a proxy if mutable. Args: @@ -3967,7 +3974,7 @@ class MutableProxy(wrapt.ObjectProxy): # Recursively wrap mutable items retrieved through this proxy. yield self._wrap_recursive(value) - def __delattr__(self, name): + def __delattr__(self, name: str): """Delete the attribute on the proxied object and mark state dirty. Args: @@ -3975,7 +3982,7 @@ class MutableProxy(wrapt.ObjectProxy): """ self._mark_dirty(super().__delattr__, args=(name,)) - def __delitem__(self, key): + def __delitem__(self, key: str): """Delete the item on the proxied object and mark state dirty. Args: @@ -3983,7 +3990,7 @@ class MutableProxy(wrapt.ObjectProxy): """ self._mark_dirty(super().__delitem__, args=(key,)) - def __setitem__(self, key, value): + def __setitem__(self, key: str, value: Any): """Set the item on the proxied object and mark state dirty. Args: @@ -3992,7 +3999,7 @@ class MutableProxy(wrapt.ObjectProxy): """ self._mark_dirty(super().__setitem__, args=(key, value)) - def __setattr__(self, name, value): + def __setattr__(self, name: str, value: Any): """Set the attribute on the proxied object and mark state dirty. If the attribute starts with "_self_", then the state is NOT marked @@ -4016,7 +4023,7 @@ class MutableProxy(wrapt.ObjectProxy): """ return copy.copy(self.__wrapped__) - def __deepcopy__(self, memo=None) -> Any: + def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Any: """Return a deepcopy of the proxy. Args: @@ -4027,7 +4034,7 @@ class MutableProxy(wrapt.ObjectProxy): """ return copy.deepcopy(self.__wrapped__, memo=memo) - def __reduce_ex__(self, protocol_version): + def __reduce_ex__(self, protocol_version: SupportsIndex): """Get the state for redis serialization. This method is called by cloudpickle to serialize the object. @@ -4091,10 +4098,10 @@ class ImmutableMutableProxy(MutableProxy): def _mark_dirty( self, - wrapped=None, - instance=None, - args=(), - kwargs=None, + wrapped: Callable | None = None, + instance: BaseState | None = None, + args: tuple = (), + kwargs: dict | None = None, ) -> Any: """Raise an exception when an attempt is made to modify the object. diff --git a/reflex/style.py b/reflex/style.py index 88513dce6..f5e424fe2 100644 --- a/reflex/style.py +++ b/reflex/style.py @@ -182,7 +182,9 @@ def convert( var_data = None # Track import/hook data from any Vars in the style dict. out = {} - def update_out_dict(return_value, keys_to_update): + def update_out_dict( + return_value: Var | dict | list | str, keys_to_update: tuple[str, ...] + ): for k in keys_to_update: out[k] = return_value diff --git a/reflex/testing.py b/reflex/testing.py index 897cb3424..25f9e7aac 100644 --- a/reflex/testing.py +++ b/reflex/testing.py @@ -90,7 +90,7 @@ else: class chdir(contextlib.AbstractContextManager): # noqa: N801 """Non thread-safe context manager to change the current working directory.""" - def __init__(self, path): + def __init__(self, path: str | Path): """Prepare contextmanager. Args: @@ -327,7 +327,7 @@ class AppHarness: return _shutdown_redis - def _start_backend(self, port=0): + def _start_backend(self, port: int = 0): if self.app_instance is None or self.app_instance.api is None: raise RuntimeError("App was not initialized.") self.backend = uvicorn.Server( @@ -430,7 +430,7 @@ class AppHarness: return self @staticmethod - def get_app_global_source(key, value): + def get_app_global_source(key: str, value: Any): """Get the source code of a global object. If value is a function or class we render the actual source of value otherwise we assign value to key. diff --git a/reflex/utils/build.py b/reflex/utils/build.py index 9ea941792..9e35ab984 100644 --- a/reflex/utils/build.py +++ b/reflex/utils/build.py @@ -27,7 +27,7 @@ def set_env_json(): ) -def generate_sitemap_config(deploy_url: str, export=False): +def generate_sitemap_config(deploy_url: str, export: bool = False): """Generate the sitemap config file. Args: diff --git a/reflex/utils/compat.py b/reflex/utils/compat.py index 339911063..e4fb5eb35 100644 --- a/reflex/utils/compat.py +++ b/reflex/utils/compat.py @@ -2,6 +2,7 @@ import contextlib import sys +from typing import Any async def windows_hot_reload_lifespan_hack(): @@ -74,7 +75,7 @@ with pydantic_v1_patch(): import sqlmodel as sqlmodel -def sqlmodel_field_has_primary_key(field) -> bool: +def sqlmodel_field_has_primary_key(field: Any) -> bool: """Determines if a field is a priamary. Args: diff --git a/reflex/utils/exceptions.py b/reflex/utils/exceptions.py index 692c7d64b..be3f6ab69 100644 --- a/reflex/utils/exceptions.py +++ b/reflex/utils/exceptions.py @@ -78,7 +78,7 @@ class VarAttributeError(ReflexError, AttributeError): class UntypedComputedVarError(ReflexError, TypeError): """Custom TypeError for untyped computed var errors.""" - def __init__(self, var_name): + def __init__(self, var_name: str): """Initialize the UntypedComputedVarError. Args: @@ -90,7 +90,7 @@ class UntypedComputedVarError(ReflexError, TypeError): class MissingAnnotationError(ReflexError, TypeError): """Custom TypeError for missing annotations.""" - def __init__(self, var_name): + def __init__(self, var_name: str): """Initialize the MissingAnnotationError. Args: diff --git a/reflex/utils/exec.py b/reflex/utils/exec.py index 22322634d..479ff816a 100644 --- a/reflex/utils/exec.py +++ b/reflex/utils/exec.py @@ -71,7 +71,9 @@ def notify_backend(): # run_process_and_launch_url is assumed to be used # only to launch the frontend # If this is not the case, might have to change the logic -def run_process_and_launch_url(run_command: list[str | None], backend_present=True): +def run_process_and_launch_url( + run_command: list[str | None], backend_present: bool = True +): """Run the process and launch the URL. Args: @@ -134,7 +136,7 @@ def run_process_and_launch_url(run_command: list[str | None], backend_present=Tr break # while True -def run_frontend(root: Path, port: str, backend_present=True): +def run_frontend(root: Path, port: str, backend_present: bool = True): """Run the frontend. Args: @@ -156,7 +158,7 @@ def run_frontend(root: Path, port: str, backend_present=True): ) -def run_frontend_prod(root: Path, port: str, backend_present=True): +def run_frontend_prod(root: Path, port: str, backend_present: bool = True): """Run the frontend. Args: @@ -265,7 +267,7 @@ def get_reload_dirs() -> list[Path]: return reload_dirs -def run_uvicorn_backend(host, port, loglevel: LogLevel): +def run_uvicorn_backend(host: str, port: int, loglevel: LogLevel): """Run the backend in development mode using Uvicorn. Args: @@ -285,7 +287,7 @@ def run_uvicorn_backend(host, port, loglevel: LogLevel): ) -def run_granian_backend(host, port, loglevel: LogLevel): +def run_granian_backend(host: str, port: int, loglevel: LogLevel): """Run the backend in development mode using Granian. Args: @@ -352,7 +354,7 @@ def run_backend_prod( run_uvicorn_backend_prod(host, port, loglevel) -def run_uvicorn_backend_prod(host, port, loglevel): +def run_uvicorn_backend_prod(host: str, port: int, loglevel: LogLevel): """Run the backend in production mode using Uvicorn. Args: @@ -404,7 +406,7 @@ def run_uvicorn_backend_prod(host, port, loglevel): ) -def run_granian_backend_prod(host, port, loglevel): +def run_granian_backend_prod(host: str, port: int, loglevel: LogLevel): """Run the backend in production mode using Granian. Args: diff --git a/reflex/utils/format.py b/reflex/utils/format.py index 7973549b0..6f05e0982 100644 --- a/reflex/utils/format.py +++ b/reflex/utils/format.py @@ -220,7 +220,7 @@ def _escape_js_string(string: str) -> str: """ # TODO: we may need to re-vist this logic after new Var API is implemented. - def escape_outside_segments(segment): + def escape_outside_segments(segment: str): """Escape backticks in segments outside of `${}`. Args: @@ -283,7 +283,7 @@ def format_var(var: Var) -> str: return str(var) -def format_route(route: str, format_case=True) -> str: +def format_route(route: str, format_case: bool = True) -> str: """Format the given route. Args: diff --git a/reflex/utils/lazy_loader.py b/reflex/utils/lazy_loader.py index 61e3967e5..eba89532d 100644 --- a/reflex/utils/lazy_loader.py +++ b/reflex/utils/lazy_loader.py @@ -1,11 +1,17 @@ """Module to implement lazy loading in reflex.""" +from __future__ import annotations + import copy import lazy_loader as lazy -def attach(package_name, submodules=None, submod_attrs=None): +def attach( + package_name: str, + submodules: set | None = None, + submod_attrs: dict | None = None, +): """Replaces a package's __getattr__, __dir__, and __all__ attributes using lazy.attach. The lazy loader __getattr__ doesn't support tuples as list values. We needed to add this functionality (tuples) in Reflex to support 'import as _' statements. This function diff --git a/reflex/utils/prerequisites.py b/reflex/utils/prerequisites.py index edaa77aba..8330a315c 100644 --- a/reflex/utils/prerequisites.py +++ b/reflex/utils/prerequisites.py @@ -884,7 +884,9 @@ def init_reflex_json(project_hash: int | None): path_ops.update_json_file(get_web_dir() / constants.Reflex.JSON, reflex_json) -def update_next_config(export=False, transpile_packages: Optional[List[str]] = None): +def update_next_config( + export: bool = False, transpile_packages: Optional[List[str]] = None +): """Update Next.js config from Reflex config. Args: @@ -1128,7 +1130,7 @@ def cached_procedure(cache_file: str, payload_fn: Callable[..., str]): The decorated function. """ - def _inner_decorator(func): + def _inner_decorator(func: Callable): def _inner(*args, **kwargs): payload = _read_cached_procedure_file(cache_file) new_payload = payload_fn(*args, **kwargs) @@ -1310,7 +1312,7 @@ def validate_bun(): raise typer.Exit(1) -def validate_frontend_dependencies(init=True): +def validate_frontend_dependencies(init: bool = True): """Validate frontend dependencies to ensure they meet requirements. Args: @@ -1634,7 +1636,9 @@ def initialize_default_app(app_name: str): initialize_app_directory(app_name) -def validate_and_create_app_using_remote_template(app_name, template, templates): +def validate_and_create_app_using_remote_template( + app_name: str, template: str, templates: dict[str, Template] +): """Validate and create an app using a remote template. Args: @@ -1846,7 +1850,7 @@ def initialize_main_module_index_from_generation(app_name: str, generation_hash: ) render_func_name = defined_funcs[-1] - def replace_content(_match): + def replace_content(_match: re.Match) -> str: return "\n".join( [ resp.text, @@ -1876,7 +1880,7 @@ def initialize_main_module_index_from_generation(app_name: str, generation_hash: main_module_path.write_text(main_module_code) -def format_address_width(address_width) -> int | None: +def format_address_width(address_width: str | None) -> int | None: """Cast address width to an int. Args: diff --git a/reflex/utils/processes.py b/reflex/utils/processes.py index 94e0fda3e..c92fb7d1a 100644 --- a/reflex/utils/processes.py +++ b/reflex/utils/processes.py @@ -9,18 +9,20 @@ import os import signal import subprocess from concurrent import futures +from pathlib import Path from typing import Callable, Generator, List, Optional, Tuple, Union import psutil import typer from redis.exceptions import RedisError +from rich.progress import Progress from reflex import constants from reflex.config import environment from reflex.utils import console, path_ops, prerequisites -def kill(pid): +def kill(pid: int): """Kill a process. Args: @@ -48,7 +50,7 @@ def get_num_workers() -> int: return (os.cpu_count() or 1) * 2 + 1 -def get_process_on_port(port) -> Optional[psutil.Process]: +def get_process_on_port(port: int) -> Optional[psutil.Process]: """Get the process on the given port. Args: @@ -71,7 +73,7 @@ def get_process_on_port(port) -> Optional[psutil.Process]: return None -def is_process_on_port(port) -> bool: +def is_process_on_port(port: int) -> bool: """Check if a process is running on the given port. Args: @@ -83,7 +85,7 @@ def is_process_on_port(port) -> bool: return get_process_on_port(port) is not None -def kill_process_on_port(port): +def kill_process_on_port(port: int): """Kill the process on the given port. Args: @@ -94,7 +96,7 @@ def kill_process_on_port(port): get_process_on_port(port).kill() # pyright: ignore [reportOptionalMemberAccess] -def change_port(port: str, _type: str) -> str: +def change_port(port: int, _type: str) -> int: """Change the port. Args: @@ -105,7 +107,7 @@ def change_port(port: str, _type: str) -> str: The new port. """ - new_port = str(int(port) + 1) + new_port = port + 1 if is_process_on_port(new_port): return change_port(new_port, _type) console.info( @@ -114,7 +116,7 @@ def change_port(port: str, _type: str) -> str: return new_port -def handle_port(service_name: str, port: str, default_port: str) -> str: +def handle_port(service_name: str, port: int, default_port: int) -> int: """Change port if the specified port is in use and is not explicitly specified as a CLI arg or config arg. otherwise tell the user the port is in use and exit the app. @@ -133,7 +135,7 @@ def handle_port(service_name: str, port: str, default_port: str) -> str: Exit:when the port is in use. """ if is_process_on_port(port): - if int(port) == int(default_port): + if port == int(default_port): return change_port(port, service_name) else: console.error(f"{service_name.capitalize()} port: {port} is already in use") @@ -141,7 +143,12 @@ def handle_port(service_name: str, port: str, default_port: str) -> str: return port -def new_process(args, run: bool = False, show_logs: bool = False, **kwargs): +def new_process( + args: str | list[str] | list[str | None] | list[str | Path | None], + run: bool = False, + show_logs: bool = False, + **kwargs, +): """Wrapper over subprocess.Popen to unify the launch of child processes. Args: @@ -157,7 +164,7 @@ def new_process(args, run: bool = False, show_logs: bool = False, **kwargs): Exit: When attempting to run a command with a None value. """ # Check for invalid command first. - if None in args: + if isinstance(args, list) and None in args: console.error(f"Invalid command: {args}") raise typer.Exit(1) @@ -191,7 +198,7 @@ def new_process(args, run: bool = False, show_logs: bool = False, **kwargs): } console.debug(f"Running command: {args}") fn = subprocess.run if run else subprocess.Popen - return fn(args, **kwargs) + return fn(args, **kwargs) # pyright: ignore [reportCallIssue, reportArgumentType] @contextlib.contextmanager @@ -247,7 +254,7 @@ def run_concurrently(*fns: Union[Callable, Tuple]) -> None: def stream_logs( message: str, process: subprocess.Popen, - progress=None, + progress: Progress | None = None, suppress_errors: bool = False, analytics_enabled: bool = False, ): @@ -375,10 +382,10 @@ def get_command_with_loglevel(command: list[str]) -> list[str]: def run_process_with_fallback( - args, + args: list[str], *, - show_status_message, - fallback=None, + show_status_message: str, + fallback: str | list | None = None, analytics_enabled: bool = False, **kwargs, ): @@ -417,7 +424,7 @@ def run_process_with_fallback( ) -def execute_command_and_return_output(command) -> str | None: +def execute_command_and_return_output(command: str) -> str | None: """Execute a command and return the output. Args: diff --git a/reflex/utils/pyi_generator.py b/reflex/utils/pyi_generator.py index 5a8cad18e..bd10e1c1c 100644 --- a/reflex/utils/pyi_generator.py +++ b/reflex/utils/pyi_generator.py @@ -83,7 +83,7 @@ DEFAULT_IMPORTS = { } -def _walk_files(path): +def _walk_files(path: str | Path): """Walk all files in a path. This can be replaced with Path.walk() in python3.12. @@ -114,7 +114,9 @@ def _relative_to_pwd(path: Path) -> Path: return path -def _get_type_hint(value, type_hint_globals, is_optional=True) -> str: +def _get_type_hint( + value: Any, type_hint_globals: dict, is_optional: bool = True +) -> str: """Resolve the type hint for value. Args: @@ -383,7 +385,7 @@ def _extract_class_props_as_ast_nodes( return kwargs -def type_to_ast(typ, cls: type) -> ast.AST: +def type_to_ast(typ: Any, cls: type) -> ast.AST: """Converts any type annotation into its AST representation. Handles nested generic types, unions, etc. @@ -443,7 +445,7 @@ def type_to_ast(typ, cls: type) -> ast.AST: ) -def _get_parent_imports(func): +def _get_parent_imports(func: Callable): _imports = {"reflex.vars": ["Var"]} for type_hint in inspect.get_annotations(func).values(): try: @@ -1052,7 +1054,7 @@ class PyiGenerator: pyi_path.write_text(pyi_content) logger.info(f"Wrote {relpath}") - def _get_init_lazy_imports(self, mod, new_tree): + def _get_init_lazy_imports(self, mod: tuple | ModuleType, new_tree: ast.AST): # retrieve the _SUBMODULES and _SUBMOD_ATTRS from an init file if present. sub_mods = getattr(mod, "_SUBMODULES", None) sub_mod_attrs = getattr(mod, "_SUBMOD_ATTRS", None) @@ -1138,7 +1140,7 @@ class PyiGenerator: if pyi_path: self.written_files.append(pyi_path) - def scan_all(self, targets, changed_files: list[Path] | None = None): + def scan_all(self, targets: list, changed_files: list[Path] | None = None): """Scan all targets for class inheriting Component and generate the .pyi files. Args: diff --git a/reflex/utils/registry.py b/reflex/utils/registry.py index d98178c61..47727d659 100644 --- a/reflex/utils/registry.py +++ b/reflex/utils/registry.py @@ -22,15 +22,15 @@ def latency(registry: str) -> int: return 10_000_000 -def average_latency(registry, attempts: int = 3) -> int: +def average_latency(registry: str, attempts: int = 3) -> int: """Get the average latency of a registry. Args: - registry (str): The URL of the registry. - attempts (int): The number of attempts to make. Defaults to 10. + registry: The URL of the registry. + attempts: The number of attempts to make. Defaults to 10. Returns: - int: The average latency of the registry in microseconds. + The average latency of the registry in microseconds. """ return sum(latency(registry) for _ in range(attempts)) // attempts diff --git a/reflex/utils/telemetry.py b/reflex/utils/telemetry.py index 67ec45b82..ecfd52428 100644 --- a/reflex/utils/telemetry.py +++ b/reflex/utils/telemetry.py @@ -162,7 +162,7 @@ def _send_event(event_data: dict) -> bool: return True -def _send(event, telemetry_enabled, **kwargs): +def _send(event: str, telemetry_enabled: bool | None, **kwargs): from reflex.config import get_config # Get the telemetry_enabled from the config if it is not specified. @@ -189,7 +189,7 @@ def send(event: str, telemetry_enabled: bool | None = None, **kwargs): kwargs: Additional data to send with the event. """ - async def async_send(event, telemetry_enabled, **kwargs): + async def async_send(event: str, telemetry_enabled: bool | None, **kwargs): return _send(event, telemetry_enabled, **kwargs) try: diff --git a/reflex/utils/types.py b/reflex/utils/types.py index 6257b1472..58fec8f3b 100644 --- a/reflex/utils/types.py +++ b/reflex/utils/types.py @@ -157,7 +157,7 @@ class Unset: @lru_cache() -def get_origin(tp): +def get_origin(tp: Any): """Get the origin of a class. Args: @@ -240,7 +240,7 @@ def is_literal(cls: GenericType) -> bool: return get_origin(cls) is Literal -def has_args(cls) -> bool: +def has_args(cls: Type) -> bool: """Check if the class has generic parameters. Args: @@ -753,7 +753,7 @@ def check_prop_in_allowed_types(prop: Any, allowed_types: Iterable) -> bool: return type_ in allowed_types -def is_encoded_fstring(value) -> bool: +def is_encoded_fstring(value: Any) -> bool: """Check if a value is an encoded Var f-string. Args: @@ -796,7 +796,7 @@ def validate_literal(key: str, value: Any, expected_type: Type, comp_name: str): ) -def validate_parameter_literals(func): +def validate_parameter_literals(func: Callable): """Decorator to check that the arguments passed to a function correspond to the correct function parameter if it (the parameter) is a literal type. diff --git a/reflex/vars/base.py b/reflex/vars/base.py index ac48355c4..4ca53eeb1 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -493,20 +493,30 @@ class Var(Generic[VAR_TYPE]): @overload def _replace( - self, _var_type: Type[OTHER_VAR_TYPE], merge_var_data=None, **kwargs: Any + self, + _var_type: Type[OTHER_VAR_TYPE], + merge_var_data: VarData | None = None, + **kwargs: Any, ) -> Var[OTHER_VAR_TYPE]: ... @overload def _replace( - self, _var_type: GenericType | None = None, merge_var_data=None, **kwargs: Any + self, + _var_type: GenericType | None = None, + merge_var_data: VarData | None = None, + **kwargs: Any, ) -> Self: ... def _replace( - self, _var_type: GenericType | None = None, merge_var_data=None, **kwargs: Any + self, + _var_type: GenericType | None = None, + merge_var_data: VarData | None = None, + **kwargs: Any, ) -> Self | Var: """Make a copy of this Var with updated fields. Args: + _var_type: The new type of the Var. merge_var_data: VarData to merge into the existing VarData. **kwargs: Var fields to update. @@ -1308,7 +1318,7 @@ class LiteralVar(Var): _var_literal_subclasses.append((cls, var_subclass)) @classmethod - def create( + def create( # pyright: ignore [reportArgumentType] cls, value: Any, _var_data: VarData | None = None, @@ -1556,7 +1566,7 @@ def figure_out_type(value: Any) -> types.GenericType: class cached_property_no_lock(functools.cached_property): # noqa: N801 """A special version of functools.cached_property that does not use a lock.""" - def __init__(self, func): + def __init__(self, func: Callable): """Initialize the cached_property_no_lock. Args: @@ -1729,7 +1739,7 @@ class CallableVar(Var): object.__setattr__(self, "fn", fn) object.__setattr__(self, "original_var", original_var) - def __call__(self, *args, **kwargs) -> Var: + def __call__(self, *args: Any, **kwargs: Any) -> Var: """Call the decorated function. Args: @@ -1885,10 +1895,16 @@ class ComputedVar(Var[RETURN_TYPE]): object.__setattr__(self, "_fget", fget) @override - def _replace(self, merge_var_data=None, **kwargs: Any) -> Self: + def _replace( + self, + _var_type: Any = None, + merge_var_data: VarData | None = None, + **kwargs: Any, + ) -> Self: """Replace the attributes of the ComputedVar. Args: + _var_type: ignored in ComputedVar. merge_var_data: VarData to merge into the existing VarData. **kwargs: Var fields to update. @@ -2002,7 +2018,7 @@ class ComputedVar(Var[RETURN_TYPE]): @overload def __get__(self, instance: BaseState, owner: Type) -> RETURN_TYPE: ... - def __get__(self, instance: BaseState | None, owner): + def __get__(self, instance: BaseState | None, owner: Type): """Get the ComputedVar value. If the value is already cached on the instance, return the cached value. @@ -2165,7 +2181,7 @@ class ComputedVar(Var[RETURN_TYPE]): self_is_top_of_stack = False return d - def mark_dirty(self, instance) -> None: + def mark_dirty(self, instance: BaseState) -> None: """Mark this ComputedVar as dirty. Args: @@ -2887,7 +2903,7 @@ MAPPING_TYPE = TypeVar("MAPPING_TYPE", bound=Mapping) class Field(Generic[FIELD_TYPE]): """Shadow class for Var to allow for type hinting in the IDE.""" - def __set__(self, instance, value: FIELD_TYPE): + def __set__(self, instance: Any, value: FIELD_TYPE): """Set the Var. Args: @@ -2896,43 +2912,43 @@ class Field(Generic[FIELD_TYPE]): """ @overload - def __get__(self: Field[bool], instance: None, owner) -> BooleanVar: ... + def __get__(self: Field[bool], instance: None, owner: Any) -> BooleanVar: ... @overload def __get__( - self: Field[int] | Field[float] | Field[int | float], instance: None, owner + self: Field[int] | Field[float] | Field[int | float], instance: None, owner: Any ) -> NumberVar: ... @overload - def __get__(self: Field[str], instance: None, owner) -> StringVar: ... + def __get__(self: Field[str], instance: None, owner: Any) -> StringVar: ... @overload - def __get__(self: Field[None], instance: None, owner) -> NoneVar: ... + def __get__(self: Field[None], instance: None, owner: Any) -> NoneVar: ... @overload def __get__( self: Field[List[V]] | Field[Set[V]] | Field[Tuple[V, ...]], instance: None, - owner, + owner: Any, ) -> ArrayVar[List[V]]: ... @overload def __get__( - self: Field[MAPPING_TYPE], instance: None, owner + self: Field[MAPPING_TYPE], instance: None, owner: Any ) -> ObjectVar[MAPPING_TYPE]: ... @overload def __get__( - self: Field[BASE_TYPE], instance: None, owner + self: Field[BASE_TYPE], instance: None, owner: Any ) -> ObjectVar[BASE_TYPE]: ... @overload - def __get__(self, instance: None, owner) -> Var[FIELD_TYPE]: ... + def __get__(self, instance: None, owner: Any) -> Var[FIELD_TYPE]: ... @overload - def __get__(self, instance, owner) -> FIELD_TYPE: ... + def __get__(self, instance: Any, owner: Any) -> FIELD_TYPE: ... - def __get__(self, instance, owner): # pyright: ignore [reportInconsistentOverload] + def __get__(self, instance: Any, owner: Any): # pyright: ignore [reportInconsistentOverload] """Get the Var. Args: diff --git a/reflex/vars/function.py b/reflex/vars/function.py index a82c4964b..e8691cfb1 100644 --- a/reflex/vars/function.py +++ b/reflex/vars/function.py @@ -210,6 +210,7 @@ class FunctionStringVar(FunctionVar[CALLABLE_TYPE]): Args: func: The function to call. + _var_type: The type of the Var. _var_data: Additional hooks and imports associated with the Var. Returns: @@ -268,6 +269,7 @@ class VarOperationCall(Generic[P, R], CachedVarOperation, Var[R]): Args: func: The function to call. *args: The arguments to call the function with. + _var_type: The type of the Var. _var_data: Additional hooks and imports associated with the Var. Returns: @@ -385,6 +387,7 @@ class ArgsFunctionOperation(CachedVarOperation, FunctionVar): return_expr: The return expression of the function. rest: The name of the rest argument. explicit_return: Whether to use explicit return syntax. + _var_type: The type of the Var. _var_data: Additional hooks and imports associated with the Var. Returns: @@ -441,6 +444,7 @@ class ArgsFunctionOperationBuilder(CachedVarOperation, BuilderFunctionVar): return_expr: The return expression of the function. rest: The name of the rest argument. explicit_return: Whether to use explicit return syntax. + _var_type: The type of the Var. _var_data: Additional hooks and imports associated with the Var. Returns: diff --git a/reflex/vars/object.py b/reflex/vars/object.py index fa8cdf8ec..ed4221e4c 100644 --- a/reflex/vars/object.py +++ b/reflex/vars/object.py @@ -253,7 +253,7 @@ class ObjectVar(Var[OBJECT_TYPE], python_types=Mapping): name: str, ) -> ObjectItemOperation: ... - def __getattr__(self, name) -> Var: + def __getattr__(self, name: str) -> Var: """Get an attribute of the var. Args: diff --git a/reflex/vars/sequence.py b/reflex/vars/sequence.py index fa1ab5bf3..5e9f6468e 100644 --- a/reflex/vars/sequence.py +++ b/reflex/vars/sequence.py @@ -780,7 +780,7 @@ class ConcatVarOperation(CachedVarOperation, StringVar[str]): """Create a var from a string value. Args: - value: The values to concatenate. + *value: The values to concatenate. _var_data: Additional hooks and imports associated with the Var. Returns: @@ -1323,6 +1323,7 @@ class LiteralArrayVar(CachedVarOperation, LiteralVar, ArrayVar[ARRAY_VAR_TYPE]): Args: value: The value to create the var from. + _var_type: The type of the var. _var_data: Additional hooks and imports associated with the Var. Returns: @@ -1618,7 +1619,9 @@ def array_contains_field_operation( @var_operation -def array_contains_operation(haystack: ArrayVar, needle: Any | Var): +def array_contains_operation( + haystack: ArrayVar, needle: Any | Var +) -> CustomVarOperationReturn[bool]: """Check if an array contains an element. Args: @@ -1661,7 +1664,7 @@ if TYPE_CHECKING: def map_array_operation( array: ArrayVar[ARRAY_VAR_TYPE], function: FunctionVar, -): +) -> CustomVarOperationReturn[List[Any]]: """Map a function over an array. Args: diff --git a/scripts/wait_for_listening_port.py b/scripts/wait_for_listening_port.py index 43581f0bc..4befa00bd 100644 --- a/scripts/wait_for_listening_port.py +++ b/scripts/wait_for_listening_port.py @@ -14,7 +14,7 @@ from typing import Tuple import psutil -def _pid_exists(pid): +def _pid_exists(pid: int): # os.kill(pid, 0) doesn't work on Windows (actually kills the PID) # psutil.pid_exists() doesn't work on Windows (does os.kill underneath) # psutil.pids() seems to return the right thing. Inefficient but doesn't matter - keeps things simple. @@ -23,7 +23,7 @@ def _pid_exists(pid): return pid in psutil.pids() -def _wait_for_port(port, server_pid, timeout) -> Tuple[bool, str]: +def _wait_for_port(port: int, server_pid: int, timeout: float) -> Tuple[bool, str]: start = time.time() print(f"Waiting for up to {timeout} seconds for port {port} to start listening.") # noqa: T201 while True: From 96ead076067d175ea8cca12b9edce764e11fad7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Wed, 29 Jan 2025 07:53:40 +0100 Subject: [PATCH 09/13] fix padding style in textarea (#4696) --- .../components/radix/themes/components/text_area.py | 12 ++++++++++++ .../components/radix/themes/components/text_area.pyi | 2 ++ 2 files changed, 14 insertions(+) diff --git a/reflex/components/radix/themes/components/text_area.py b/reflex/components/radix/themes/components/text_area.py index 83fa8a593..caf98eb2d 100644 --- a/reflex/components/radix/themes/components/text_area.py +++ b/reflex/components/radix/themes/components/text_area.py @@ -96,5 +96,17 @@ class TextArea(RadixThemesComponent, elements.Textarea): return DebounceInput.create(super().create(*children, **props)) return super().create(*children, **props) + def add_style(self): + """Add the style to the component. + + Returns: + The style of the component. + """ + added_style: dict[str, dict] = {} + added_style.setdefault("& textarea", {}) + if "padding" in self.style: + added_style["& textarea"]["padding"] = self.style.pop("padding") + return added_style + text_area = TextArea.create diff --git a/reflex/components/radix/themes/components/text_area.pyi b/reflex/components/radix/themes/components/text_area.pyi index f0903ba98..e1e40c936 100644 --- a/reflex/components/radix/themes/components/text_area.pyi +++ b/reflex/components/radix/themes/components/text_area.pyi @@ -268,4 +268,6 @@ class TextArea(RadixThemesComponent, elements.Textarea): """ ... + def add_style(self): ... + text_area = TextArea.create From 58f87a6aa7057bbaec9ead8aff4216c19a625f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Wed, 29 Jan 2025 07:54:23 +0100 Subject: [PATCH 10/13] only allow item inside root (#4697) --- reflex/components/radix/themes/components/radio_cards.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/reflex/components/radix/themes/components/radio_cards.py b/reflex/components/radix/themes/components/radio_cards.py index e075a1ba2..4a9aefc99 100644 --- a/reflex/components/radix/themes/components/radio_cards.py +++ b/reflex/components/radix/themes/components/radio_cards.py @@ -85,6 +85,8 @@ class RadioCardsItem(RadixThemesComponent): # When true, indicates that the user must check the radio item before the owning form can be submitted. required: Var[bool] + _valid_parents: list[str] = ["RadioCardsRoot"] + class RadioCards(SimpleNamespace): """RadioCards components namespace.""" From 5beea25b3171256c72b964e9200be542850b5b19 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Tue, 28 Jan 2025 22:56:38 -0800 Subject: [PATCH 11/13] improve var create typing (#4701) --- .../components/radix/primitives/accordion.py | 3 +- .../components/radix/primitives/accordion.pyi | 4 +- reflex/vars/base.py | 53 ++++++++++++++++++- reflex/vars/number.py | 2 +- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/reflex/components/radix/primitives/accordion.py b/reflex/components/radix/primitives/accordion.py index 170b3ed9c..2d9c7ae96 100644 --- a/reflex/components/radix/primitives/accordion.py +++ b/reflex/components/radix/primitives/accordion.py @@ -196,8 +196,9 @@ class AccordionItem(AccordionComponent): # The header of the accordion item. header: Var[Union[Component, str]] + # The content of the accordion item. - content: Var[Union[Component, str]] = Var.create(None) + content: Var[Union[Component, str, None]] = Var.create(None) _valid_children: List[str] = [ "AccordionHeader", diff --git a/reflex/components/radix/primitives/accordion.pyi b/reflex/components/radix/primitives/accordion.pyi index 03208f496..447451d11 100644 --- a/reflex/components/radix/primitives/accordion.pyi +++ b/reflex/components/radix/primitives/accordion.pyi @@ -308,7 +308,9 @@ class AccordionItem(AccordionComponent): value: Optional[Union[Var[str], str]] = None, disabled: Optional[Union[Var[bool], bool]] = None, header: Optional[Union[Component, Var[Union[Component, str]], str]] = None, - content: Optional[Union[Component, Var[Union[Component, str]], str]] = None, + content: Optional[ + Union[Component, Var[Optional[Union[Component, str]]], str] + ] = None, color_scheme: Optional[ Union[ Literal[ diff --git a/reflex/vars/base.py b/reflex/vars/base.py index 4ca53eeb1..6f4eddf42 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -80,6 +80,7 @@ if TYPE_CHECKING: VAR_TYPE = TypeVar("VAR_TYPE", covariant=True) OTHER_VAR_TYPE = TypeVar("OTHER_VAR_TYPE") +STRING_T = TypeVar("STRING_T", bound=str) warnings.filterwarnings("ignore", message="fields may not start with an underscore") @@ -550,12 +551,60 @@ class Var(Generic[VAR_TYPE]): return value_with_replaced + @overload + @classmethod + def create( # type: ignore[override] + cls, + value: bool, + _var_data: VarData | None = None, + ) -> BooleanVar: ... + + @overload + @classmethod + def create( # type: ignore[override] + cls, + value: int, + _var_data: VarData | None = None, + ) -> NumberVar[int]: ... + + @overload @classmethod def create( cls, - value: Any, + value: float, _var_data: VarData | None = None, - ) -> Var: + ) -> NumberVar[float]: ... + + @overload + @classmethod + def create( + cls, + value: STRING_T, + _var_data: VarData | None = None, + ) -> StringVar[STRING_T]: ... + + @overload + @classmethod + def create( + cls, + value: None, + _var_data: VarData | None = None, + ) -> NoneVar: ... + + @overload + @classmethod + def create( + cls, + value: OTHER_VAR_TYPE, + _var_data: VarData | None = None, + ) -> Var[OTHER_VAR_TYPE]: ... + + @classmethod + def create( + cls, + value: OTHER_VAR_TYPE, + _var_data: VarData | None = None, + ) -> Var[OTHER_VAR_TYPE]: """Create a var from a value. Args: diff --git a/reflex/vars/number.py b/reflex/vars/number.py index 475c08b55..050dc2329 100644 --- a/reflex/vars/number.py +++ b/reflex/vars/number.py @@ -31,7 +31,7 @@ from .base import ( var_operation_return, ) -NUMBER_T = TypeVar("NUMBER_T", int, float, Union[int, float], bool) +NUMBER_T = TypeVar("NUMBER_T", int, float, bool) if TYPE_CHECKING: from .sequence import ArrayVar From 58e63f387fe255ae888edc0637501993b8feb663 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Tue, 28 Jan 2025 23:02:14 -0800 Subject: [PATCH 12/13] assert that .render returns jsonable values (#4708) * assert that .render returns jsonable values * render component default --- .../.templates/jinja/web/pages/utils.js.jinja2 | 2 +- reflex/components/tags/tag.py | 17 +++++++++++++++++ tests/units/components/core/test_match.py | 4 ++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/reflex/.templates/jinja/web/pages/utils.js.jinja2 b/reflex/.templates/jinja/web/pages/utils.js.jinja2 index 624e3bee8..567ca6e60 100644 --- a/reflex/.templates/jinja/web/pages/utils.js.jinja2 +++ b/reflex/.templates/jinja/web/pages/utils.js.jinja2 @@ -90,7 +90,7 @@ break; {% endfor %} default: - return {{ component.default }}; + return {{ render(component.default) }}; break; } })() diff --git a/reflex/components/tags/tag.py b/reflex/components/tags/tag.py index 8569d5d50..8a6326dc0 100644 --- a/reflex/components/tags/tag.py +++ b/reflex/components/tags/tag.py @@ -65,7 +65,24 @@ class Tag: Yields: Tuple[str, Any]: The field name and value. """ + from reflex.components.component import BaseComponent + for field in dataclasses.fields(self): + value = getattr(self, field.name) + if isinstance(value, list): + children = [] + for child in value: + if isinstance(child, BaseComponent): + children.append(child.render()) + else: + children.append(child) + yield field.name, children + continue + if isinstance(value, BaseComponent): + yield field.name, value.render() + continue + if callable(value) and not isinstance(value, Var): + continue yield field.name, getattr(self, field.name) def add_props(self, **kwargs: Optional[Any]) -> Tag: diff --git a/tests/units/components/core/test_match.py b/tests/units/components/core/test_match.py index e563873ec..b765750ee 100644 --- a/tests/units/components/core/test_match.py +++ b/tests/units/components/core/test_match.py @@ -78,7 +78,7 @@ def test_match_components(): assert fifth_return_value_render["name"] == "RadixThemesText" assert fifth_return_value_render["children"][0]["contents"] == '{"sixth value"}' - default = match_child["default"].render() + default = match_child["default"] assert default["name"] == "RadixThemesText" assert default["children"][0]["contents"] == '{"default value"}' @@ -153,7 +153,7 @@ def test_match_on_component_without_default(): match_comp = Match.create(MatchState.value, *match_case_tuples) default = match_comp.render()["children"][0]["default"] - assert isinstance(default, Fragment) + assert isinstance(default, dict) and default["name"] == Fragment.__name__ def test_match_on_var_no_default(): From 1e8e82ec0e0fa121426d3198c000c461a872d905 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Tue, 28 Jan 2025 23:03:22 -0800 Subject: [PATCH 13/13] allow functools partial with foreach (#4709) --- reflex/components/core/foreach.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/reflex/components/core/foreach.py b/reflex/components/core/foreach.py index c9fbe5bc5..30dda9c6a 100644 --- a/reflex/components/core/foreach.py +++ b/reflex/components/core/foreach.py @@ -2,6 +2,7 @@ from __future__ import annotations +import functools import inspect from typing import Any, Callable, Iterable @@ -97,9 +98,20 @@ class Foreach(Component): # Determine the index var name based on the params accepted by render_fn. props["index_var_name"] = params[1].name else: + render_fn = self.render_fn # Otherwise, use a deterministic index, based on the render function bytecode. code_hash = ( - hash(self.render_fn.__code__) + hash( + getattr( + render_fn, + "__code__", + ( + repr(self.render_fn) + if not isinstance(render_fn, functools.partial) + else render_fn.func.__code__ + ), + ) + ) .to_bytes( length=8, byteorder="big",