From 3f538865b5c4f3d777f528e0c8958e1da9f7fa9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Thu, 26 Sep 2024 01:22:52 +0200 Subject: [PATCH] reorganize all tests in a single top folder (#3981) * lift node version restraint to allow more recent version if already installed * add node test for latest version * change python version * use purple for debug logs * update workflow * add playwright dev dependency * update workflow * change test * oops * improve test * update test * fix tests * mv units tests to a subfolder * reorganize tests * fix install * update test_state * revert node changes and only keep new tests organization * move integration tests in tests/integration * fix integration workflow * fix dockerfile workflow * fix dockerfile workflow 2 * fix shared_state --- .github/workflows/check_node_latest.yml | 39 +++ .github/workflows/integration_app_harness.yml | 2 +- .../workflows/reflex_init_in_docker_test.yml | 4 +- .github/workflows/unit_tests.yml | 6 +- .pre-commit-config.yaml | 2 +- CONTRIBUTING.md | 2 +- poetry.lock | 239 ++++++++++++------ pyproject.toml | 2 + reflex/utils/console.py | 2 +- .../integration}/__init__.py | 0 .../integration}/conftest.py | 0 .../integration}/init-test/Dockerfile | 0 .../init-test/in_docker_test_script.sh | 2 +- .../integration}/shared/state.py | 0 .../integration}/test_background_task.py | 0 .../integration}/test_call_script.py | 0 .../integration}/test_client_storage.py | 0 .../integration}/test_component_state.py | 0 .../integration}/test_computed_vars.py | 0 .../integration}/test_connection_banner.py | 0 .../integration}/test_deploy_url.py | 0 .../integration}/test_dynamic_components.py | 0 .../integration}/test_dynamic_routes.py | 0 .../integration}/test_event_actions.py | 0 .../integration}/test_event_chain.py | 0 .../integration}/test_exception_handlers.py | 0 .../integration}/test_form_submit.py | 0 .../integration}/test_input.py | 0 .../integration}/test_large_state.py | 0 .../integration}/test_lifespan.py | 0 .../integration}/test_login_flow.py | 0 .../integration}/test_media.py | 0 .../integration}/test_navigation.py | 0 .../integration}/test_server_side_event.py | 0 .../integration}/test_shared_state.py | 2 +- .../integration}/test_state_inheritance.py | 0 .../integration}/test_table.py | 0 .../integration}/test_tailwind.py | 0 .../integration}/test_upload.py | 0 .../integration}/test_urls.py | 0 .../integration}/test_var_operations.py | 0 {integration => tests/integration}/utils.py | 0 tests/test_node_version.py | 73 ++++++ tests/units/__init__.py | 5 + tests/{ => units}/compiler/__init__.py | 0 tests/{ => units}/compiler/test_compiler.py | 0 .../compiler/test_compiler_utils.py | 0 tests/{ => units}/components/__init__.py | 0 .../{ => units}/components/base/test_bare.py | 0 .../{ => units}/components/base/test_link.py | 0 .../components/base/test_script.py | 0 tests/{ => units}/components/core/__init__.py | 0 .../components/core/test_banner.py | 0 .../components/core/test_colors.py | 0 .../{ => units}/components/core/test_cond.py | 0 .../components/core/test_debounce.py | 0 .../components/core/test_foreach.py | 0 .../{ => units}/components/core/test_html.py | 0 .../{ => units}/components/core/test_match.py | 0 .../components/core/test_responsive.py | 0 .../components/core/test_upload.py | 0 .../components/datadisplay/__init__.py | 0 .../components/datadisplay/conftest.py | 0 .../components/datadisplay/test_code.py | 0 .../components/datadisplay/test_dataeditor.py | 0 .../components/datadisplay/test_datatable.py | 0 tests/{ => units}/components/el/test_html.py | 0 .../{ => units}/components/forms/__init__.py | 0 .../{ => units}/components/forms/test_form.py | 0 .../components/forms/test_uploads.py | 0 .../components/graphing/__init__.py | 0 .../components/graphing/test_plotly.py | 0 .../components/graphing/test_recharts.py | 0 .../{ => units}/components/layout/__init__.py | 0 .../components/lucide/test_icon.py | 0 .../{ => units}/components/media/__init__.py | 0 .../components/media/test_image.py | 0 .../components/radix/test_icon_button.py | 0 .../components/radix/test_layout.py | 0 .../components/recharts/test_cartesian.py | 0 .../components/recharts/test_polar.py | 0 .../{ => units}/components/test_component.py | 0 .../test_component_future_annotations.py | 0 .../components/test_component_state.py | 0 tests/{ => units}/components/test_tag.py | 0 .../components/typography/__init__.py | 0 .../components/typography/test_markdown.py | 0 tests/{ => units}/conftest.py | 0 .../{ => units}/experimental/custom_script.js | 0 tests/{ => units}/experimental/test_assets.py | 0 tests/{ => units}/middleware/__init__.py | 0 tests/{ => units}/middleware/conftest.py | 0 .../middleware/test_hydrate_middleware.py | 0 tests/{ => units}/states/__init__.py | 0 tests/{ => units}/states/mutation.py | 0 tests/{ => units}/states/upload.py | 0 tests/{ => units}/test_app.py | 0 .../{ => units}/test_attribute_access_type.py | 0 tests/{ => units}/test_base.py | 0 tests/{ => units}/test_config.py | 0 tests/{ => units}/test_db_config.py | 0 tests/{ => units}/test_event.py | 0 tests/{ => units}/test_health_endpoint.py | 0 tests/{ => units}/test_model.py | 0 tests/{ => units}/test_page.py | 0 tests/{ => units}/test_prerequisites.py | 0 tests/{ => units}/test_route.py | 0 tests/{ => units}/test_sqlalchemy.py | 0 tests/{ => units}/test_state.py | 20 +- tests/{ => units}/test_state_tree.py | 0 tests/{ => units}/test_style.py | 0 tests/{ => units}/test_telemetry.py | 0 tests/{ => units}/test_testing.py | 0 tests/{ => units}/test_var.py | 0 tests/{ => units}/utils/__init__.py | 0 tests/{ => units}/utils/test_format.py | 2 +- tests/{ => units}/utils/test_imports.py | 0 tests/{ => units}/utils/test_serializers.py | 0 tests/{ => units}/utils/test_types.py | 0 tests/{ => units}/utils/test_utils.py | 0 tests/{ => units}/vars/test_base.py | 0 121 files changed, 306 insertions(+), 96 deletions(-) create mode 100644 .github/workflows/check_node_latest.yml rename {integration => tests/integration}/__init__.py (100%) rename {integration => tests/integration}/conftest.py (100%) rename {integration => tests/integration}/init-test/Dockerfile (100%) rename {integration => tests/integration}/init-test/in_docker_test_script.sh (96%) rename {integration => tests/integration}/shared/state.py (100%) rename {integration => tests/integration}/test_background_task.py (100%) rename {integration => tests/integration}/test_call_script.py (100%) rename {integration => tests/integration}/test_client_storage.py (100%) rename {integration => tests/integration}/test_component_state.py (100%) rename {integration => tests/integration}/test_computed_vars.py (100%) rename {integration => tests/integration}/test_connection_banner.py (100%) rename {integration => tests/integration}/test_deploy_url.py (100%) rename {integration => tests/integration}/test_dynamic_components.py (100%) rename {integration => tests/integration}/test_dynamic_routes.py (100%) rename {integration => tests/integration}/test_event_actions.py (100%) rename {integration => tests/integration}/test_event_chain.py (100%) rename {integration => tests/integration}/test_exception_handlers.py (100%) rename {integration => tests/integration}/test_form_submit.py (100%) rename {integration => tests/integration}/test_input.py (100%) rename {integration => tests/integration}/test_large_state.py (100%) rename {integration => tests/integration}/test_lifespan.py (100%) rename {integration => tests/integration}/test_login_flow.py (100%) rename {integration => tests/integration}/test_media.py (100%) rename {integration => tests/integration}/test_navigation.py (100%) rename {integration => tests/integration}/test_server_side_event.py (100%) rename {integration => tests/integration}/test_shared_state.py (96%) rename {integration => tests/integration}/test_state_inheritance.py (100%) rename {integration => tests/integration}/test_table.py (100%) rename {integration => tests/integration}/test_tailwind.py (100%) rename {integration => tests/integration}/test_upload.py (100%) rename {integration => tests/integration}/test_urls.py (100%) rename {integration => tests/integration}/test_var_operations.py (100%) rename {integration => tests/integration}/utils.py (100%) create mode 100644 tests/test_node_version.py create mode 100644 tests/units/__init__.py rename tests/{ => units}/compiler/__init__.py (100%) rename tests/{ => units}/compiler/test_compiler.py (100%) rename tests/{ => units}/compiler/test_compiler_utils.py (100%) rename tests/{ => units}/components/__init__.py (100%) rename tests/{ => units}/components/base/test_bare.py (100%) rename tests/{ => units}/components/base/test_link.py (100%) rename tests/{ => units}/components/base/test_script.py (100%) rename tests/{ => units}/components/core/__init__.py (100%) rename tests/{ => units}/components/core/test_banner.py (100%) rename tests/{ => units}/components/core/test_colors.py (100%) rename tests/{ => units}/components/core/test_cond.py (100%) rename tests/{ => units}/components/core/test_debounce.py (100%) rename tests/{ => units}/components/core/test_foreach.py (100%) rename tests/{ => units}/components/core/test_html.py (100%) rename tests/{ => units}/components/core/test_match.py (100%) rename tests/{ => units}/components/core/test_responsive.py (100%) rename tests/{ => units}/components/core/test_upload.py (100%) rename tests/{ => units}/components/datadisplay/__init__.py (100%) rename tests/{ => units}/components/datadisplay/conftest.py (100%) rename tests/{ => units}/components/datadisplay/test_code.py (100%) rename tests/{ => units}/components/datadisplay/test_dataeditor.py (100%) rename tests/{ => units}/components/datadisplay/test_datatable.py (100%) rename tests/{ => units}/components/el/test_html.py (100%) rename tests/{ => units}/components/forms/__init__.py (100%) rename tests/{ => units}/components/forms/test_form.py (100%) rename tests/{ => units}/components/forms/test_uploads.py (100%) rename tests/{ => units}/components/graphing/__init__.py (100%) rename tests/{ => units}/components/graphing/test_plotly.py (100%) rename tests/{ => units}/components/graphing/test_recharts.py (100%) rename tests/{ => units}/components/layout/__init__.py (100%) rename tests/{ => units}/components/lucide/test_icon.py (100%) rename tests/{ => units}/components/media/__init__.py (100%) rename tests/{ => units}/components/media/test_image.py (100%) rename tests/{ => units}/components/radix/test_icon_button.py (100%) rename tests/{ => units}/components/radix/test_layout.py (100%) rename tests/{ => units}/components/recharts/test_cartesian.py (100%) rename tests/{ => units}/components/recharts/test_polar.py (100%) rename tests/{ => units}/components/test_component.py (100%) rename tests/{ => units}/components/test_component_future_annotations.py (100%) rename tests/{ => units}/components/test_component_state.py (100%) rename tests/{ => units}/components/test_tag.py (100%) rename tests/{ => units}/components/typography/__init__.py (100%) rename tests/{ => units}/components/typography/test_markdown.py (100%) rename tests/{ => units}/conftest.py (100%) rename tests/{ => units}/experimental/custom_script.js (100%) rename tests/{ => units}/experimental/test_assets.py (100%) rename tests/{ => units}/middleware/__init__.py (100%) rename tests/{ => units}/middleware/conftest.py (100%) rename tests/{ => units}/middleware/test_hydrate_middleware.py (100%) rename tests/{ => units}/states/__init__.py (100%) rename tests/{ => units}/states/mutation.py (100%) rename tests/{ => units}/states/upload.py (100%) rename tests/{ => units}/test_app.py (100%) rename tests/{ => units}/test_attribute_access_type.py (100%) rename tests/{ => units}/test_base.py (100%) rename tests/{ => units}/test_config.py (100%) rename tests/{ => units}/test_db_config.py (100%) rename tests/{ => units}/test_event.py (100%) rename tests/{ => units}/test_health_endpoint.py (100%) rename tests/{ => units}/test_model.py (100%) rename tests/{ => units}/test_page.py (100%) rename tests/{ => units}/test_prerequisites.py (100%) rename tests/{ => units}/test_route.py (100%) rename tests/{ => units}/test_sqlalchemy.py (100%) rename tests/{ => units}/test_state.py (99%) rename tests/{ => units}/test_state_tree.py (100%) rename tests/{ => units}/test_style.py (100%) rename tests/{ => units}/test_telemetry.py (100%) rename tests/{ => units}/test_testing.py (100%) rename tests/{ => units}/test_var.py (100%) rename tests/{ => units}/utils/__init__.py (100%) rename tests/{ => units}/utils/test_format.py (99%) rename tests/{ => units}/utils/test_imports.py (100%) rename tests/{ => units}/utils/test_serializers.py (100%) rename tests/{ => units}/utils/test_types.py (100%) rename tests/{ => units}/utils/test_utils.py (100%) rename tests/{ => units}/vars/test_base.py (100%) diff --git a/.github/workflows/check_node_latest.yml b/.github/workflows/check_node_latest.yml new file mode 100644 index 000000000..945786c05 --- /dev/null +++ b/.github/workflows/check_node_latest.yml @@ -0,0 +1,39 @@ +name: integration-node-latest + +on: + push: + branches: + - main + pull_request: + branches: + - main + +env: + TELEMETRY_ENABLED: false + +jobs: + check_latest_node: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.12'] + node-version: ['node'] + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup_build_env + with: + python-version: ${{ matrix.python-version }} + run-poetry-install: true + create-venv-at-path: .venv + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + - run: | + poetry run uv pip install pyvirtualdisplay pillow + poetry run playwright install --with-deps + - run: | + # poetry run pytest tests/test_node_version.py + poetry run pytest tests/integration + + + diff --git a/.github/workflows/integration_app_harness.yml b/.github/workflows/integration_app_harness.yml index 93412aa71..c11e6e01c 100644 --- a/.github/workflows/integration_app_harness.yml +++ b/.github/workflows/integration_app_harness.yml @@ -51,7 +51,7 @@ jobs: SCREENSHOT_DIR: /tmp/screenshots REDIS_URL: ${{ matrix.state_manager == 'redis' && 'redis://localhost:6379' || '' }} run: | - poetry run pytest integration + poetry run pytest tests/integration - uses: actions/upload-artifact@v4 name: Upload failed test screenshots if: always() diff --git a/.github/workflows/reflex_init_in_docker_test.yml b/.github/workflows/reflex_init_in_docker_test.yml index b34efd2f6..ce56a1310 100644 --- a/.github/workflows/reflex_init_in_docker_test.yml +++ b/.github/workflows/reflex_init_in_docker_test.yml @@ -28,5 +28,5 @@ jobs: # Run reflex init in a docker container # cwd is repo root - docker build -f integration/init-test/Dockerfile -t reflex-init-test integration/init-test - docker run --rm -v $(pwd):/reflex-repo/ reflex-init-test /reflex-repo/integration/init-test/in_docker_test_script.sh + docker build -f tests/integration/init-test/Dockerfile -t reflex-init-test tests/integration/init-test + docker run --rm -v $(pwd):/reflex-repo/ reflex-init-test /reflex-repo/tests/integration/init-test/in_docker_test_script.sh diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 333c54cb3..09e489949 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -65,17 +65,17 @@ jobs: - name: Run unit tests run: | export PYTHONUNBUFFERED=1 - poetry run pytest tests --cov --no-cov-on-fail --cov-report= + poetry run pytest tests/units --cov --no-cov-on-fail --cov-report= - name: Run unit tests w/ redis if: ${{ matrix.os == 'ubuntu-latest' }} run: | export PYTHONUNBUFFERED=1 export REDIS_URL=redis://localhost:6379 - poetry run pytest tests --cov --no-cov-on-fail --cov-report= + poetry run pytest tests/units --cov --no-cov-on-fail --cov-report= # Change to explicitly install v1 when reflex-hosting-cli is compatible with v2 - name: Run unit tests w/ pydantic v1 run: | export PYTHONUNBUFFERED=1 poetry run uv pip install "pydantic~=1.10" - poetry run pytest tests --cov --no-cov-on-fail --cov-report= + poetry run pytest tests/units --cov --no-cov-on-fail --cov-report= - run: poetry run coverage html diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fbd88c485..609364a6e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: rev: v0.4.10 hooks: - id: ruff-format - args: [integration, reflex, tests] + args: [reflex, tests] - id: ruff args: ["--fix", "--exit-non-zero-on-fix"] exclude: '^integration/benchmarks/' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index af195997a..fc8398013 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,7 +69,7 @@ In your `reflex` directory run make sure all the unit tests are still passing us This will fail if code coverage is below 70%. ``` bash -poetry run pytest tests --cov --no-cov-on-fail --cov-report= +poetry run pytest tests/units --cov --no-cov-on-fail --cov-report= ``` Next make sure all the following tests pass. This ensures that every new change has proper documentation and type checking. diff --git a/poetry.lock b/poetry.lock index 7a836a021..f94a3832a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -616,84 +616,69 @@ typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "greenlet" -version = "3.1.1" +version = "3.0.3" description = "Lightweight in-process concurrent programming" optional = false python-versions = ">=3.7" 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"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc"}, - {file = "greenlet-3.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617"}, - {file = "greenlet-3.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7"}, - {file = "greenlet-3.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6"}, - {file = "greenlet-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80"}, - {file = "greenlet-3.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383"}, - {file = "greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a"}, - {file = "greenlet-3.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511"}, - {file = "greenlet-3.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395"}, - {file = "greenlet-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39"}, - {file = "greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36"}, - {file = "greenlet-3.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9"}, - {file = "greenlet-3.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0"}, - {file = "greenlet-3.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942"}, - {file = "greenlet-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01"}, - {file = "greenlet-3.1.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4"}, - {file = "greenlet-3.1.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e"}, - {file = "greenlet-3.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1"}, - {file = "greenlet-3.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c"}, - {file = "greenlet-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b"}, - {file = "greenlet-3.1.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822"}, - {file = "greenlet-3.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01"}, - {file = "greenlet-3.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc"}, - {file = "greenlet-3.1.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de"}, - {file = "greenlet-3.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa"}, - {file = "greenlet-3.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af"}, - {file = "greenlet-3.1.1-cp37-cp37m-win32.whl", hash = "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798"}, - {file = "greenlet-3.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef"}, - {file = "greenlet-3.1.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8"}, - {file = "greenlet-3.1.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1"}, - {file = "greenlet-3.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd"}, - {file = "greenlet-3.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7"}, - {file = "greenlet-3.1.1-cp38-cp38-win32.whl", hash = "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef"}, - {file = "greenlet-3.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d"}, - {file = "greenlet-3.1.1-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145"}, - {file = "greenlet-3.1.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c"}, - {file = "greenlet-3.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e"}, - {file = "greenlet-3.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e"}, - {file = "greenlet-3.1.1-cp39-cp39-win32.whl", hash = "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c"}, - {file = "greenlet-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22"}, - {file = "greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467"}, + {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"}, + {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"}, + {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"}, + {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"}, + {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"}, + {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"}, + {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"}, + {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"}, + {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"}, + {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"}, + {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"}, + {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"}, + {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"}, + {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"}, + {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"}, + {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"}, + {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"}, + {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"}, + {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"}, + {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"}, + {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"}, + {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"}, + {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"}, + {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"}, + {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"}, + {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"}, + {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"}, + {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"}, ] [package.extras] @@ -1527,6 +1512,26 @@ docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-a test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] type = ["mypy (>=1.11.2)"] +[[package]] +name = "playwright" +version = "1.47.0" +description = "A high-level API to automate web browsers" +optional = false +python-versions = ">=3.8" +files = [ + {file = "playwright-1.47.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:f205df24edb925db1a4ab62f1ab0da06f14bb69e382efecfb0deedc4c7f4b8cd"}, + {file = "playwright-1.47.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7fc820faf6885f69a52ba4ec94124e575d3c4a4003bf29200029b4a4f2b2d0ab"}, + {file = "playwright-1.47.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:8e212dc472ff19c7d46ed7e900191c7a786ce697556ac3f1615986ec3aa00341"}, + {file = "playwright-1.47.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:a1935672531963e4b2a321de5aa59b982fb92463ee6e1032dd7326378e462955"}, + {file = "playwright-1.47.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0a1b61473d6f7f39c5d77d4800b3cbefecb03344c90b98f3fbcae63294ad249"}, + {file = "playwright-1.47.0-py3-none-win32.whl", hash = "sha256:1b977ed81f6bba5582617684a21adab9bad5676d90a357ebf892db7bdf4a9974"}, + {file = "playwright-1.47.0-py3-none-win_amd64.whl", hash = "sha256:0ec1056042d2e86088795a503347407570bffa32cbe20748e5d4c93dba085280"}, +] + +[package.dependencies] +greenlet = "3.0.3" +pyee = "12.0.0" + [[package]] name = "plotly" version = "5.24.1" @@ -1750,6 +1755,23 @@ files = [ [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +[[package]] +name = "pyee" +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" +files = [ + {file = "pyee-12.0.0-py3-none-any.whl", hash = "sha256:7b14b74320600049ccc7d0e0b1becd3b4bd0a03c745758225e31a59f4095c990"}, + {file = "pyee-12.0.0.tar.gz", hash = "sha256:c480603f4aa2927d4766eb41fa82793fe60a82cbfdb8d688e0d08c55a534e145"}, +] + +[package.dependencies] +typing-extensions = "*" + +[package.extras] +dev = ["black", "build", "flake8", "flake8-black", "isort", "jupyter-console", "mkdocs", "mkdocs-include-markdown-plugin", "mkdocstrings[python]", "pytest", "pytest-asyncio", "pytest-trio", "sphinx", "toml", "tox", "trio", "trio", "trio-typing", "twine", "twisted", "validate-pyproject[all]"] + [[package]] name = "pygments" version = "2.18.0" @@ -1845,6 +1867,24 @@ pytest = ">=7.0.0" docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] +[[package]] +name = "pytest-base-url" +version = "2.1.0" +description = "pytest plugin for URL based testing" +optional = false +python-versions = ">=3.8" +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"}, +] + +[package.dependencies] +pytest = ">=7.0.0" +requests = ">=2.9" + +[package.extras] +test = ["black (>=22.1.0)", "flake8 (>=4.0.1)", "pre-commit (>=2.17.0)", "pytest-localserver (>=0.7.1)", "tox (>=3.24.5)"] + [[package]] name = "pytest-benchmark" version = "4.0.0" @@ -1900,6 +1940,23 @@ pytest = ">=6.2.5" [package.extras] dev = ["pre-commit", "pytest-asyncio", "tox"] +[[package]] +name = "pytest-playwright" +version = "0.5.2" +description = "A pytest wrapper with fixtures for Playwright to automate web browsers" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_playwright-0.5.2-py3-none-any.whl", hash = "sha256:2c5720591364a1cdf66610b972ff8492512bc380953e043c85f705b78b2ed582"}, + {file = "pytest_playwright-0.5.2.tar.gz", hash = "sha256:c6d603df9e6c50b35f057b0528e11d41c0963283e98c257267117f5ed6ba1924"}, +] + +[package.dependencies] +playwright = ">=1.18" +pytest = ">=6.2.4,<9.0.0" +pytest-base-url = ">=1.0.0,<3.0.0" +python-slugify = ">=6.0.0,<9.0.0" + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -1944,6 +2001,23 @@ files = [ {file = "python_multipart-0.0.10.tar.gz", hash = "sha256:46eb3c6ce6fdda5fb1a03c7e11d490e407c6930a2703fe7aef4da71c374688fa"}, ] +[[package]] +name = "python-slugify" +version = "8.0.4" +description = "A Python slugify application that also handles Unicode" +optional = false +python-versions = ">=3.7" +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"}, +] + +[package.dependencies] +text-unidecode = ">=1.3" + +[package.extras] +unidecode = ["Unidecode (>=1.1.1)"] + [[package]] name = "python-socketio" version = "5.11.4" @@ -2334,7 +2408,9 @@ python-versions = ">=3.7" files = [ {file = "SQLAlchemy-2.0.35-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:67219632be22f14750f0d1c70e62f204ba69d28f62fd6432ba05ab295853de9b"}, {file = "SQLAlchemy-2.0.35-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4668bd8faf7e5b71c0319407b608f278f279668f358857dbfd10ef1954ac9f90"}, + {file = "SQLAlchemy-2.0.35-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb8bea573863762bbf45d1e13f87c2d2fd32cee2dbd50d050f83f87429c9e1ea"}, {file = "SQLAlchemy-2.0.35-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f552023710d4b93d8fb29a91fadf97de89c5926c6bd758897875435f2a939f33"}, + {file = "SQLAlchemy-2.0.35-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:016b2e665f778f13d3c438651dd4de244214b527a275e0acf1d44c05bc6026a9"}, {file = "SQLAlchemy-2.0.35-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7befc148de64b6060937231cbff8d01ccf0bfd75aa26383ffdf8d82b12ec04ff"}, {file = "SQLAlchemy-2.0.35-cp310-cp310-win32.whl", hash = "sha256:22b83aed390e3099584b839b93f80a0f4a95ee7f48270c97c90acd40ee646f0b"}, {file = "SQLAlchemy-2.0.35-cp310-cp310-win_amd64.whl", hash = "sha256:a29762cd3d116585278ffb2e5b8cc311fb095ea278b96feef28d0b423154858e"}, @@ -2371,7 +2447,9 @@ files = [ {file = "SQLAlchemy-2.0.35-cp38-cp38-win_amd64.whl", hash = "sha256:0375a141e1c0878103eb3d719eb6d5aa444b490c96f3fedab8471c7f6ffe70ee"}, {file = "SQLAlchemy-2.0.35-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ccae5de2a0140d8be6838c331604f91d6fafd0735dbdcee1ac78fc8fbaba76b4"}, {file = "SQLAlchemy-2.0.35-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2a275a806f73e849e1c309ac11108ea1a14cd7058577aba962cd7190e27c9e3c"}, + {file = "SQLAlchemy-2.0.35-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:732e026240cdd1c1b2e3ac515c7a23820430ed94292ce33806a95869c46bd139"}, {file = "SQLAlchemy-2.0.35-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:890da8cd1941fa3dab28c5bac3b9da8502e7e366f895b3b8e500896f12f94d11"}, + {file = "SQLAlchemy-2.0.35-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0d8326269dbf944b9201911b0d9f3dc524d64779a07518199a58384c3d37a44"}, {file = "SQLAlchemy-2.0.35-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b76d63495b0508ab9fc23f8152bac63205d2a704cd009a2b0722f4c8e0cba8e0"}, {file = "SQLAlchemy-2.0.35-cp39-cp39-win32.whl", hash = "sha256:69683e02e8a9de37f17985905a5eca18ad651bf592314b4d3d799029797d0eb3"}, {file = "SQLAlchemy-2.0.35-cp39-cp39-win_amd64.whl", hash = "sha256:aee110e4ef3c528f3abbc3c2018c121e708938adeeff9006428dd7c8555e9b3f"}, @@ -2493,6 +2571,17 @@ files = [ doc = ["reno", "sphinx"] test = ["pytest", "tornado (>=4.5)", "typeguard"] +[[package]] +name = "text-unidecode" +version = "1.3" +description = "The most basic Text::Unidecode port" +optional = false +python-versions = "*" +files = [ + {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, + {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, +] + [[package]] name = "toml" version = "0.10.2" @@ -2922,4 +3011,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "df66545bb3f79e356e3a91866306f8b18b800aeadf1f98ac184644f986a83d95" +content-hash = "adccd071775567aeefe219261aeb9e222906c865745f03edb1e770edc79c44ac" diff --git a/pyproject.toml b/pyproject.toml index c8a62e195..335fc440e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,6 +77,8 @@ asynctest = ">=0.13.0,<1.0" pre-commit = ">=3.2.1" selenium = ">=4.11.0,<5.0" pytest-benchmark = ">=4.0.0,<5.0" +playwright = ">=1.46.0" +pytest-playwright = ">=0.5.1" [tool.poetry.scripts] reflex = "reflex.reflex:cli" diff --git a/reflex/utils/console.py b/reflex/utils/console.py index 69500b32f..20c699e20 100644 --- a/reflex/utils/console.py +++ b/reflex/utils/console.py @@ -58,7 +58,7 @@ def debug(msg: str, **kwargs): kwargs: Keyword arguments to pass to the print function. """ if is_debug(): - msg_ = f"[blue]Debug: {msg}[/blue]" + msg_ = f"[purple]Debug: {msg}[/purple]" if progress := kwargs.pop("progress", None): progress.console.print(msg_, **kwargs) else: diff --git a/integration/__init__.py b/tests/integration/__init__.py similarity index 100% rename from integration/__init__.py rename to tests/integration/__init__.py diff --git a/integration/conftest.py b/tests/integration/conftest.py similarity index 100% rename from integration/conftest.py rename to tests/integration/conftest.py diff --git a/integration/init-test/Dockerfile b/tests/integration/init-test/Dockerfile similarity index 100% rename from integration/init-test/Dockerfile rename to tests/integration/init-test/Dockerfile diff --git a/integration/init-test/in_docker_test_script.sh b/tests/integration/init-test/in_docker_test_script.sh similarity index 96% rename from integration/init-test/in_docker_test_script.sh rename to tests/integration/init-test/in_docker_test_script.sh index 4e898ac99..31d245588 100755 --- a/integration/init-test/in_docker_test_script.sh +++ b/tests/integration/init-test/in_docker_test_script.sh @@ -13,7 +13,7 @@ function do_export () { reflex init --template "$template" reflex export ( - cd "$SCRIPTPATH/../.." + cd "$SCRIPTPATH/../../.." scripts/integration.sh ~/"$template" dev pkill -9 -f 'next-server|python3' || true sleep 10 diff --git a/integration/shared/state.py b/tests/integration/shared/state.py similarity index 100% rename from integration/shared/state.py rename to tests/integration/shared/state.py diff --git a/integration/test_background_task.py b/tests/integration/test_background_task.py similarity index 100% rename from integration/test_background_task.py rename to tests/integration/test_background_task.py diff --git a/integration/test_call_script.py b/tests/integration/test_call_script.py similarity index 100% rename from integration/test_call_script.py rename to tests/integration/test_call_script.py diff --git a/integration/test_client_storage.py b/tests/integration/test_client_storage.py similarity index 100% rename from integration/test_client_storage.py rename to tests/integration/test_client_storage.py diff --git a/integration/test_component_state.py b/tests/integration/test_component_state.py similarity index 100% rename from integration/test_component_state.py rename to tests/integration/test_component_state.py diff --git a/integration/test_computed_vars.py b/tests/integration/test_computed_vars.py similarity index 100% rename from integration/test_computed_vars.py rename to tests/integration/test_computed_vars.py diff --git a/integration/test_connection_banner.py b/tests/integration/test_connection_banner.py similarity index 100% rename from integration/test_connection_banner.py rename to tests/integration/test_connection_banner.py diff --git a/integration/test_deploy_url.py b/tests/integration/test_deploy_url.py similarity index 100% rename from integration/test_deploy_url.py rename to tests/integration/test_deploy_url.py diff --git a/integration/test_dynamic_components.py b/tests/integration/test_dynamic_components.py similarity index 100% rename from integration/test_dynamic_components.py rename to tests/integration/test_dynamic_components.py diff --git a/integration/test_dynamic_routes.py b/tests/integration/test_dynamic_routes.py similarity index 100% rename from integration/test_dynamic_routes.py rename to tests/integration/test_dynamic_routes.py diff --git a/integration/test_event_actions.py b/tests/integration/test_event_actions.py similarity index 100% rename from integration/test_event_actions.py rename to tests/integration/test_event_actions.py diff --git a/integration/test_event_chain.py b/tests/integration/test_event_chain.py similarity index 100% rename from integration/test_event_chain.py rename to tests/integration/test_event_chain.py diff --git a/integration/test_exception_handlers.py b/tests/integration/test_exception_handlers.py similarity index 100% rename from integration/test_exception_handlers.py rename to tests/integration/test_exception_handlers.py diff --git a/integration/test_form_submit.py b/tests/integration/test_form_submit.py similarity index 100% rename from integration/test_form_submit.py rename to tests/integration/test_form_submit.py diff --git a/integration/test_input.py b/tests/integration/test_input.py similarity index 100% rename from integration/test_input.py rename to tests/integration/test_input.py diff --git a/integration/test_large_state.py b/tests/integration/test_large_state.py similarity index 100% rename from integration/test_large_state.py rename to tests/integration/test_large_state.py diff --git a/integration/test_lifespan.py b/tests/integration/test_lifespan.py similarity index 100% rename from integration/test_lifespan.py rename to tests/integration/test_lifespan.py diff --git a/integration/test_login_flow.py b/tests/integration/test_login_flow.py similarity index 100% rename from integration/test_login_flow.py rename to tests/integration/test_login_flow.py diff --git a/integration/test_media.py b/tests/integration/test_media.py similarity index 100% rename from integration/test_media.py rename to tests/integration/test_media.py diff --git a/integration/test_navigation.py b/tests/integration/test_navigation.py similarity index 100% rename from integration/test_navigation.py rename to tests/integration/test_navigation.py diff --git a/integration/test_server_side_event.py b/tests/integration/test_server_side_event.py similarity index 100% rename from integration/test_server_side_event.py rename to tests/integration/test_server_side_event.py diff --git a/integration/test_shared_state.py b/tests/integration/test_shared_state.py similarity index 96% rename from integration/test_shared_state.py rename to tests/integration/test_shared_state.py index a1a3d6080..6f59c5142 100644 --- a/integration/test_shared_state.py +++ b/tests/integration/test_shared_state.py @@ -12,7 +12,7 @@ from reflex.testing import AppHarness, WebDriver def SharedStateApp(): """Test that shared state works as expected.""" import reflex as rx - from integration.shared.state import SharedState + from tests.integration.shared.state import SharedState class State(SharedState): pass diff --git a/integration/test_state_inheritance.py b/tests/integration/test_state_inheritance.py similarity index 100% rename from integration/test_state_inheritance.py rename to tests/integration/test_state_inheritance.py diff --git a/integration/test_table.py b/tests/integration/test_table.py similarity index 100% rename from integration/test_table.py rename to tests/integration/test_table.py diff --git a/integration/test_tailwind.py b/tests/integration/test_tailwind.py similarity index 100% rename from integration/test_tailwind.py rename to tests/integration/test_tailwind.py diff --git a/integration/test_upload.py b/tests/integration/test_upload.py similarity index 100% rename from integration/test_upload.py rename to tests/integration/test_upload.py diff --git a/integration/test_urls.py b/tests/integration/test_urls.py similarity index 100% rename from integration/test_urls.py rename to tests/integration/test_urls.py diff --git a/integration/test_var_operations.py b/tests/integration/test_var_operations.py similarity index 100% rename from integration/test_var_operations.py rename to tests/integration/test_var_operations.py diff --git a/integration/utils.py b/tests/integration/utils.py similarity index 100% rename from integration/utils.py rename to tests/integration/utils.py diff --git a/tests/test_node_version.py b/tests/test_node_version.py new file mode 100644 index 000000000..9555eb524 --- /dev/null +++ b/tests/test_node_version.py @@ -0,0 +1,73 @@ +"""Test for latest node version being able to run reflex.""" + +from __future__ import annotations + +from typing import Any, Generator + +import httpx +import pytest +from playwright.sync_api import Page, expect + +from reflex.testing import AppHarness + + +def TestNodeVersionApp(): + """A test app for node latest version.""" + import reflex as rx + from reflex.utils.prerequisites import get_node_version + + class TestNodeVersionConfig(rx.Config): + pass + + class TestNodeVersionState(rx.State): + @rx.var + def node_version(self) -> str: + return str(get_node_version()) + + app = rx.App() + + @app.add_page + def index(): + return rx.heading("Node Version check v", TestNodeVersionState.node_version) + + +@pytest.fixture() +def node_version_app(tmp_path) -> Generator[AppHarness, Any, None]: + """Fixture to start TestNodeVersionApp app at tmp_path via AppHarness. + + Args: + tmp_path: pytest tmp_path fixture + + Yields: + running AppHarness instance + """ + with AppHarness.create( + root=tmp_path, + app_source=TestNodeVersionApp, # type: ignore + ) as harness: + yield harness + + +def test_node_version(node_version_app: AppHarness, page: Page): + """Test for latest node version being able to run reflex. + + Args: + node_version_app: running AppHarness instance + page: playwright page instance + """ + + def get_latest_node_version(): + response = httpx.get("https://nodejs.org/dist/index.json") + versions = response.json() + + # Assuming the first entry in the API response is the most recent version + if versions: + latest_version = versions[0]["version"] + return latest_version + return None + + assert node_version_app.frontend_url is not None + page.goto(node_version_app.frontend_url) + expect(page.get_by_role("heading")).to_have_text( + f"Node Version check {get_latest_node_version()}" + ) diff --git a/tests/units/__init__.py b/tests/units/__init__.py new file mode 100644 index 000000000..d0196603c --- /dev/null +++ b/tests/units/__init__.py @@ -0,0 +1,5 @@ +"""Root directory for tests.""" + +import os + +from reflex import constants diff --git a/tests/compiler/__init__.py b/tests/units/compiler/__init__.py similarity index 100% rename from tests/compiler/__init__.py rename to tests/units/compiler/__init__.py diff --git a/tests/compiler/test_compiler.py b/tests/units/compiler/test_compiler.py similarity index 100% rename from tests/compiler/test_compiler.py rename to tests/units/compiler/test_compiler.py diff --git a/tests/compiler/test_compiler_utils.py b/tests/units/compiler/test_compiler_utils.py similarity index 100% rename from tests/compiler/test_compiler_utils.py rename to tests/units/compiler/test_compiler_utils.py diff --git a/tests/components/__init__.py b/tests/units/components/__init__.py similarity index 100% rename from tests/components/__init__.py rename to tests/units/components/__init__.py diff --git a/tests/components/base/test_bare.py b/tests/units/components/base/test_bare.py similarity index 100% rename from tests/components/base/test_bare.py rename to tests/units/components/base/test_bare.py diff --git a/tests/components/base/test_link.py b/tests/units/components/base/test_link.py similarity index 100% rename from tests/components/base/test_link.py rename to tests/units/components/base/test_link.py diff --git a/tests/components/base/test_script.py b/tests/units/components/base/test_script.py similarity index 100% rename from tests/components/base/test_script.py rename to tests/units/components/base/test_script.py diff --git a/tests/components/core/__init__.py b/tests/units/components/core/__init__.py similarity index 100% rename from tests/components/core/__init__.py rename to tests/units/components/core/__init__.py diff --git a/tests/components/core/test_banner.py b/tests/units/components/core/test_banner.py similarity index 100% rename from tests/components/core/test_banner.py rename to tests/units/components/core/test_banner.py diff --git a/tests/components/core/test_colors.py b/tests/units/components/core/test_colors.py similarity index 100% rename from tests/components/core/test_colors.py rename to tests/units/components/core/test_colors.py diff --git a/tests/components/core/test_cond.py b/tests/units/components/core/test_cond.py similarity index 100% rename from tests/components/core/test_cond.py rename to tests/units/components/core/test_cond.py diff --git a/tests/components/core/test_debounce.py b/tests/units/components/core/test_debounce.py similarity index 100% rename from tests/components/core/test_debounce.py rename to tests/units/components/core/test_debounce.py diff --git a/tests/components/core/test_foreach.py b/tests/units/components/core/test_foreach.py similarity index 100% rename from tests/components/core/test_foreach.py rename to tests/units/components/core/test_foreach.py diff --git a/tests/components/core/test_html.py b/tests/units/components/core/test_html.py similarity index 100% rename from tests/components/core/test_html.py rename to tests/units/components/core/test_html.py diff --git a/tests/components/core/test_match.py b/tests/units/components/core/test_match.py similarity index 100% rename from tests/components/core/test_match.py rename to tests/units/components/core/test_match.py diff --git a/tests/components/core/test_responsive.py b/tests/units/components/core/test_responsive.py similarity index 100% rename from tests/components/core/test_responsive.py rename to tests/units/components/core/test_responsive.py diff --git a/tests/components/core/test_upload.py b/tests/units/components/core/test_upload.py similarity index 100% rename from tests/components/core/test_upload.py rename to tests/units/components/core/test_upload.py diff --git a/tests/components/datadisplay/__init__.py b/tests/units/components/datadisplay/__init__.py similarity index 100% rename from tests/components/datadisplay/__init__.py rename to tests/units/components/datadisplay/__init__.py diff --git a/tests/components/datadisplay/conftest.py b/tests/units/components/datadisplay/conftest.py similarity index 100% rename from tests/components/datadisplay/conftest.py rename to tests/units/components/datadisplay/conftest.py diff --git a/tests/components/datadisplay/test_code.py b/tests/units/components/datadisplay/test_code.py similarity index 100% rename from tests/components/datadisplay/test_code.py rename to tests/units/components/datadisplay/test_code.py diff --git a/tests/components/datadisplay/test_dataeditor.py b/tests/units/components/datadisplay/test_dataeditor.py similarity index 100% rename from tests/components/datadisplay/test_dataeditor.py rename to tests/units/components/datadisplay/test_dataeditor.py diff --git a/tests/components/datadisplay/test_datatable.py b/tests/units/components/datadisplay/test_datatable.py similarity index 100% rename from tests/components/datadisplay/test_datatable.py rename to tests/units/components/datadisplay/test_datatable.py diff --git a/tests/components/el/test_html.py b/tests/units/components/el/test_html.py similarity index 100% rename from tests/components/el/test_html.py rename to tests/units/components/el/test_html.py diff --git a/tests/components/forms/__init__.py b/tests/units/components/forms/__init__.py similarity index 100% rename from tests/components/forms/__init__.py rename to tests/units/components/forms/__init__.py diff --git a/tests/components/forms/test_form.py b/tests/units/components/forms/test_form.py similarity index 100% rename from tests/components/forms/test_form.py rename to tests/units/components/forms/test_form.py diff --git a/tests/components/forms/test_uploads.py b/tests/units/components/forms/test_uploads.py similarity index 100% rename from tests/components/forms/test_uploads.py rename to tests/units/components/forms/test_uploads.py diff --git a/tests/components/graphing/__init__.py b/tests/units/components/graphing/__init__.py similarity index 100% rename from tests/components/graphing/__init__.py rename to tests/units/components/graphing/__init__.py diff --git a/tests/components/graphing/test_plotly.py b/tests/units/components/graphing/test_plotly.py similarity index 100% rename from tests/components/graphing/test_plotly.py rename to tests/units/components/graphing/test_plotly.py diff --git a/tests/components/graphing/test_recharts.py b/tests/units/components/graphing/test_recharts.py similarity index 100% rename from tests/components/graphing/test_recharts.py rename to tests/units/components/graphing/test_recharts.py diff --git a/tests/components/layout/__init__.py b/tests/units/components/layout/__init__.py similarity index 100% rename from tests/components/layout/__init__.py rename to tests/units/components/layout/__init__.py diff --git a/tests/components/lucide/test_icon.py b/tests/units/components/lucide/test_icon.py similarity index 100% rename from tests/components/lucide/test_icon.py rename to tests/units/components/lucide/test_icon.py diff --git a/tests/components/media/__init__.py b/tests/units/components/media/__init__.py similarity index 100% rename from tests/components/media/__init__.py rename to tests/units/components/media/__init__.py diff --git a/tests/components/media/test_image.py b/tests/units/components/media/test_image.py similarity index 100% rename from tests/components/media/test_image.py rename to tests/units/components/media/test_image.py diff --git a/tests/components/radix/test_icon_button.py b/tests/units/components/radix/test_icon_button.py similarity index 100% rename from tests/components/radix/test_icon_button.py rename to tests/units/components/radix/test_icon_button.py diff --git a/tests/components/radix/test_layout.py b/tests/units/components/radix/test_layout.py similarity index 100% rename from tests/components/radix/test_layout.py rename to tests/units/components/radix/test_layout.py diff --git a/tests/components/recharts/test_cartesian.py b/tests/units/components/recharts/test_cartesian.py similarity index 100% rename from tests/components/recharts/test_cartesian.py rename to tests/units/components/recharts/test_cartesian.py diff --git a/tests/components/recharts/test_polar.py b/tests/units/components/recharts/test_polar.py similarity index 100% rename from tests/components/recharts/test_polar.py rename to tests/units/components/recharts/test_polar.py diff --git a/tests/components/test_component.py b/tests/units/components/test_component.py similarity index 100% rename from tests/components/test_component.py rename to tests/units/components/test_component.py diff --git a/tests/components/test_component_future_annotations.py b/tests/units/components/test_component_future_annotations.py similarity index 100% rename from tests/components/test_component_future_annotations.py rename to tests/units/components/test_component_future_annotations.py diff --git a/tests/components/test_component_state.py b/tests/units/components/test_component_state.py similarity index 100% rename from tests/components/test_component_state.py rename to tests/units/components/test_component_state.py diff --git a/tests/components/test_tag.py b/tests/units/components/test_tag.py similarity index 100% rename from tests/components/test_tag.py rename to tests/units/components/test_tag.py diff --git a/tests/components/typography/__init__.py b/tests/units/components/typography/__init__.py similarity index 100% rename from tests/components/typography/__init__.py rename to tests/units/components/typography/__init__.py diff --git a/tests/components/typography/test_markdown.py b/tests/units/components/typography/test_markdown.py similarity index 100% rename from tests/components/typography/test_markdown.py rename to tests/units/components/typography/test_markdown.py diff --git a/tests/conftest.py b/tests/units/conftest.py similarity index 100% rename from tests/conftest.py rename to tests/units/conftest.py diff --git a/tests/experimental/custom_script.js b/tests/units/experimental/custom_script.js similarity index 100% rename from tests/experimental/custom_script.js rename to tests/units/experimental/custom_script.js diff --git a/tests/experimental/test_assets.py b/tests/units/experimental/test_assets.py similarity index 100% rename from tests/experimental/test_assets.py rename to tests/units/experimental/test_assets.py diff --git a/tests/middleware/__init__.py b/tests/units/middleware/__init__.py similarity index 100% rename from tests/middleware/__init__.py rename to tests/units/middleware/__init__.py diff --git a/tests/middleware/conftest.py b/tests/units/middleware/conftest.py similarity index 100% rename from tests/middleware/conftest.py rename to tests/units/middleware/conftest.py diff --git a/tests/middleware/test_hydrate_middleware.py b/tests/units/middleware/test_hydrate_middleware.py similarity index 100% rename from tests/middleware/test_hydrate_middleware.py rename to tests/units/middleware/test_hydrate_middleware.py diff --git a/tests/states/__init__.py b/tests/units/states/__init__.py similarity index 100% rename from tests/states/__init__.py rename to tests/units/states/__init__.py diff --git a/tests/states/mutation.py b/tests/units/states/mutation.py similarity index 100% rename from tests/states/mutation.py rename to tests/units/states/mutation.py diff --git a/tests/states/upload.py b/tests/units/states/upload.py similarity index 100% rename from tests/states/upload.py rename to tests/units/states/upload.py diff --git a/tests/test_app.py b/tests/units/test_app.py similarity index 100% rename from tests/test_app.py rename to tests/units/test_app.py diff --git a/tests/test_attribute_access_type.py b/tests/units/test_attribute_access_type.py similarity index 100% rename from tests/test_attribute_access_type.py rename to tests/units/test_attribute_access_type.py diff --git a/tests/test_base.py b/tests/units/test_base.py similarity index 100% rename from tests/test_base.py rename to tests/units/test_base.py diff --git a/tests/test_config.py b/tests/units/test_config.py similarity index 100% rename from tests/test_config.py rename to tests/units/test_config.py diff --git a/tests/test_db_config.py b/tests/units/test_db_config.py similarity index 100% rename from tests/test_db_config.py rename to tests/units/test_db_config.py diff --git a/tests/test_event.py b/tests/units/test_event.py similarity index 100% rename from tests/test_event.py rename to tests/units/test_event.py diff --git a/tests/test_health_endpoint.py b/tests/units/test_health_endpoint.py similarity index 100% rename from tests/test_health_endpoint.py rename to tests/units/test_health_endpoint.py diff --git a/tests/test_model.py b/tests/units/test_model.py similarity index 100% rename from tests/test_model.py rename to tests/units/test_model.py diff --git a/tests/test_page.py b/tests/units/test_page.py similarity index 100% rename from tests/test_page.py rename to tests/units/test_page.py diff --git a/tests/test_prerequisites.py b/tests/units/test_prerequisites.py similarity index 100% rename from tests/test_prerequisites.py rename to tests/units/test_prerequisites.py diff --git a/tests/test_route.py b/tests/units/test_route.py similarity index 100% rename from tests/test_route.py rename to tests/units/test_route.py diff --git a/tests/test_sqlalchemy.py b/tests/units/test_sqlalchemy.py similarity index 100% rename from tests/test_sqlalchemy.py rename to tests/units/test_sqlalchemy.py diff --git a/tests/test_state.py b/tests/units/test_state.py similarity index 99% rename from tests/test_state.py rename to tests/units/test_state.py index 21584fff9..89aad1536 100644 --- a/tests/test_state.py +++ b/tests/units/test_state.py @@ -43,7 +43,7 @@ from reflex.testing import chdir from reflex.utils import format, prerequisites, types from reflex.utils.format import json_dumps from reflex.vars.base import ComputedVar, Var -from tests.states.mutation import MutableSQLAModel, MutableTestState +from tests.units.states.mutation import MutableSQLAModel, MutableTestState from .states import GenState @@ -440,26 +440,28 @@ def test_get_substates(): def test_get_name(): """Test getting the name of a state.""" - assert TestState.get_name() == "tests___test_state____test_state" - assert ChildState.get_name() == "tests___test_state____child_state" - assert ChildState2.get_name() == "tests___test_state____child_state2" - assert GrandchildState.get_name() == "tests___test_state____grandchild_state" + assert TestState.get_name() == "tests___units___test_state____test_state" + assert ChildState.get_name() == "tests___units___test_state____child_state" + assert ChildState2.get_name() == "tests___units___test_state____child_state2" + assert ( + GrandchildState.get_name() == "tests___units___test_state____grandchild_state" + ) def test_get_full_name(): """Test getting the full name.""" - assert TestState.get_full_name() == "tests___test_state____test_state" + assert TestState.get_full_name() == "tests___units___test_state____test_state" assert ( ChildState.get_full_name() - == "tests___test_state____test_state.tests___test_state____child_state" + == "tests___units___test_state____test_state.tests___units___test_state____child_state" ) assert ( ChildState2.get_full_name() - == "tests___test_state____test_state.tests___test_state____child_state2" + == "tests___units___test_state____test_state.tests___units___test_state____child_state2" ) assert ( GrandchildState.get_full_name() - == "tests___test_state____test_state.tests___test_state____child_state.tests___test_state____grandchild_state" + == "tests___units___test_state____test_state.tests___units___test_state____child_state.tests___units___test_state____grandchild_state" ) diff --git a/tests/test_state_tree.py b/tests/units/test_state_tree.py similarity index 100% rename from tests/test_state_tree.py rename to tests/units/test_state_tree.py diff --git a/tests/test_style.py b/tests/units/test_style.py similarity index 100% rename from tests/test_style.py rename to tests/units/test_style.py diff --git a/tests/test_telemetry.py b/tests/units/test_telemetry.py similarity index 100% rename from tests/test_telemetry.py rename to tests/units/test_telemetry.py diff --git a/tests/test_testing.py b/tests/units/test_testing.py similarity index 100% rename from tests/test_testing.py rename to tests/units/test_testing.py diff --git a/tests/test_var.py b/tests/units/test_var.py similarity index 100% rename from tests/test_var.py rename to tests/units/test_var.py diff --git a/tests/utils/__init__.py b/tests/units/utils/__init__.py similarity index 100% rename from tests/utils/__init__.py rename to tests/units/utils/__init__.py diff --git a/tests/utils/test_format.py b/tests/units/utils/test_format.py similarity index 99% rename from tests/utils/test_format.py rename to tests/units/utils/test_format.py index b108f9dc2..4ec5099f5 100644 --- a/tests/utils/test_format.py +++ b/tests/units/utils/test_format.py @@ -13,7 +13,7 @@ from reflex.utils import format from reflex.utils.serializers import serialize_figure from reflex.vars.base import LiteralVar, Var from reflex.vars.object import ObjectVar -from tests.test_state import ( +from tests.units.test_state import ( ChildState, ChildState2, ChildState3, diff --git a/tests/utils/test_imports.py b/tests/units/utils/test_imports.py similarity index 100% rename from tests/utils/test_imports.py rename to tests/units/utils/test_imports.py diff --git a/tests/utils/test_serializers.py b/tests/units/utils/test_serializers.py similarity index 100% rename from tests/utils/test_serializers.py rename to tests/units/utils/test_serializers.py diff --git a/tests/utils/test_types.py b/tests/units/utils/test_types.py similarity index 100% rename from tests/utils/test_types.py rename to tests/units/utils/test_types.py diff --git a/tests/utils/test_utils.py b/tests/units/utils/test_utils.py similarity index 100% rename from tests/utils/test_utils.py rename to tests/units/utils/test_utils.py diff --git a/tests/vars/test_base.py b/tests/units/vars/test_base.py similarity index 100% rename from tests/vars/test_base.py rename to tests/units/vars/test_base.py