Explorar o código

Merge remote-tracking branch 'origin/main' into disable-auto-setters

Benedikt Bartscher hai 1 mes
pai
achega
1e3dc9bc2d
Modificáronse 100 ficheiros con 1483 adicións e 7058 borrados
  1. 12 12
      .devcontainer/devcontainer.json
  2. 10 9
      .github/ISSUE_TEMPLATE/bug_report.md
  3. 32 0
      .github/ISSUE_TEMPLATE/build_issue.md
  4. 32 0
      .github/ISSUE_TEMPLATE/cloud_issue.md
  5. 6 6
      .github/ISSUE_TEMPLATE/custom_component_request.md
  6. 4 4
      .github/ISSUE_TEMPLATE/enhancement_request.md
  7. 32 0
      .github/ISSUE_TEMPLATE/enterprise_issue.md
  8. 4 5
      .github/ISSUE_TEMPLATE/feature_request.md
  9. 28 70
      .github/actions/setup_build_env/action.yml
  10. 2 4
      .github/pull_request_template.md
  11. 15 26
      .github/workflows/benchmarks.yml
  12. 0 40
      .github/workflows/check_generated_pyi.yml
  13. 7 8
      .github/workflows/check_node_latest.yml
  14. 10 11
      .github/workflows/check_outdated_dependencies.yml
  15. 4 4
      .github/workflows/dependency-review.yml
  16. 6 5
      .github/workflows/integration_app_harness.yml
  17. 29 39
      .github/workflows/integration_tests.yml
  18. 20 30
      .github/workflows/integration_tests_wsl.yml
  19. 14 5
      .github/workflows/performance.yml
  20. 8 11
      .github/workflows/pre-commit.yml
  21. 6 4
      .github/workflows/reflex_init_in_docker_test.yml
  22. 12 12
      .github/workflows/unit_tests.yml
  23. 6 1
      .gitignore
  24. 13 8
      .pre-commit-config.yaml
  25. 11 11
      CODE_OF_CONDUCT.md
  26. 21 24
      CONTRIBUTING.md
  27. 14 20
      README.md
  28. 3 3
      SECURITY.md
  29. 1 1
      docker-example/README.md
  30. 24 23
      docker-example/production-app-platform/README.md
  31. 2 2
      docker-example/production-compose/README.md
  32. 2 2
      docker-example/production-compose/compose.prod.yaml
  33. 2 2
      docker-example/production-compose/compose.tools.yaml
  34. 5 5
      docker-example/production-compose/compose.yaml
  35. 1 1
      docker-example/production-one-port/Dockerfile
  36. 6 4
      docker-example/production-one-port/README.md
  37. 3 2
      docker-example/simple-one-port/README.md
  38. 4 3
      docker-example/simple-two-port/README.md
  39. 13 13
      docs/DEBUGGING.md
  40. 12 19
      docs/de/README.md
  41. 12 12
      docs/es/README.md
  42. 0 1
      docs/in/README.md
  43. 14 12
      docs/it/README.md
  44. 0 1
      docs/ja/README.md
  45. 16 20
      docs/kr/README.md
  46. 16 23
      docs/pe/README.md
  47. 15 18
      docs/pt/pt_br/README.md
  48. 3 7
      docs/tr/README.md
  49. 15 23
      docs/vi/README.md
  50. 13 20
      docs/zh/zh_cn/README.md
  51. 13 23
      docs/zh/zh_tw/README.md
  52. 50 0
      hatch_build.py
  53. 0 3192
      poetry.lock
  54. 126 0
      pyi_hashes.json
  55. 98 67
      pyproject.toml
  56. 1 1
      reflex/.templates/jinja/web/pages/_app.js.jinja2
  57. 6 3
      reflex/.templates/jinja/web/pages/custom_component.js.jinja2
  58. 10 2
      reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js
  59. 26 21
      reflex/.templates/web/components/shiki/code.js
  60. 1 1
      reflex/.templates/web/postcss.config.js
  61. 18 16
      reflex/.templates/web/utils/client_side_routing.js
  62. 1 1
      reflex/.templates/web/utils/helpers/dataeditor.js
  63. 30 30
      reflex/.templates/web/utils/helpers/range.js
  64. 37 6
      reflex/.templates/web/utils/state.js
  65. 2 1
      reflex/__init__.py
  66. 0 214
      reflex/__init__.pyi
  67. 6 2
      reflex/admin.py
  68. 47 14
      reflex/app.py
  69. 22 30
      reflex/app_mixins/middleware.py
  70. 0 33
      reflex/app_module_for_backend.py
  71. 3 3
      reflex/base.py
  72. 123 10
      reflex/compiler/compiler.py
  73. 4 4
      reflex/compiler/utils.py
  74. 0 23
      reflex/components/__init__.pyi
  75. 0 26
      reflex/components/base/__init__.pyi
  76. 0 47
      reflex/components/base/app_wrap.pyi
  77. 3 3
      reflex/components/base/bare.py
  78. 0 57
      reflex/components/base/body.pyi
  79. 0 242
      reflex/components/base/document.pyi
  80. 0 68
      reflex/components/base/error_boundary.pyi
  81. 0 59
      reflex/components/base/fragment.pyi
  82. 0 105
      reflex/components/base/head.pyi
  83. 0 121
      reflex/components/base/link.pyi
  84. 0 226
      reflex/components/base/meta.pyi
  85. 0 84
      reflex/components/base/script.pyi
  86. 0 57
      reflex/components/base/strict_mode.pyi
  87. 243 119
      reflex/components/component.py
  88. 0 42
      reflex/components/core/__init__.pyi
  89. 8 1
      reflex/components/core/auto_scroll.py
  90. 0 257
      reflex/components/core/auto_scroll.pyi
  91. 7 3
      reflex/components/core/banner.py
  92. 0 701
      reflex/components/core/banner.pyi
  93. 3 3
      reflex/components/core/client_side_routing.py
  94. 0 110
      reflex/components/core/client_side_routing.pyi
  95. 0 71
      reflex/components/core/clipboard.pyi
  96. 35 35
      reflex/components/core/cond.py
  97. 1 1
      reflex/components/core/debounce.py
  98. 0 73
      reflex/components/core/debounce.pyi
  99. 19 6
      reflex/components/core/foreach.py
  100. 0 258
      reflex/components/core/html.pyi

+ 12 - 12
.devcontainer/devcontainer.json

@@ -1,14 +1,14 @@
 {
-	"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bookworm",
-	"postCreateCommand": "/bin/bash -c 'python -m pip install poetry && python -m poetry install & git clone https://github.com/reflex-dev/reflex-examples; wait'",
-	"forwardPorts": [3000, 8000],
-	"portsAttributes": {
-		"3000": {
-			"label": "Frontend",
-			"onAutoForward": "notify"
-		},
-		"8000": {
-			"label": "Backend"
-		}
-	}
+  "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bookworm",
+  "postCreateCommand": "/bin/bash -c 'python -m pip install uv && python -m uv sync & git clone https://github.com/reflex-dev/reflex-examples; wait'",
+  "forwardPorts": [3000, 8000],
+  "portsAttributes": {
+    "3000": {
+      "label": "Frontend",
+      "onAutoForward": "notify"
+    },
+    "8000": {
+      "label": "Backend"
+    }
+  }
 }

+ 10 - 9
.github/ISSUE_TEMPLATE/bug_report.md

@@ -1,9 +1,8 @@
 ---
 name: Bug report
 about: Create a report to help us improve
-title: ''
-assignees: ''
-
+title: ""
+assignees: ""
 ---
 
 **Describe the bug**
@@ -11,7 +10,8 @@ A clear and concise description of what the bug is.
 
 **To Reproduce**
 Steps to reproduce the behavior:
- - Code/Link to Repo:
+
+- Code/Link to Repo:
 
 **Expected behavior**
 A clear and concise description of what you expected to happen.
@@ -20,10 +20,11 @@ A clear and concise description of what you expected to happen.
 If applicable, add screenshots to help explain your problem.
 
 **Specifics (please complete the following information):**
- - Python Version:
- - Reflex Version:
- - OS: 
- - Browser (Optional):
- 
+
+- Python Version:
+- Reflex Version:
+- OS:
+- Browser (Optional):
+
 **Additional context**
 Add any other context about the problem here.

+ 32 - 0
.github/ISSUE_TEMPLATE/build_issue.md

@@ -0,0 +1,32 @@
+---
+name: Build Issue
+about: Report an issue related to reflex.build
+title: "[BUILD] " # This acts as a hint, but users can change it.
+labels: build
+assignees: ""
+---
+
+## Describe the issue
+
+Provide details about the issue.
+
+...
+
+## Expected behavior
+
+What should have happened?
+
+...
+
+## Steps to reproduce (if applicable)
+
+1.
+2.
+3.
+
+## Environment
+
+- Reflex Version:
+- Python Version:
+- OS:
+- Browser:

+ 32 - 0
.github/ISSUE_TEMPLATE/cloud_issue.md

@@ -0,0 +1,32 @@
+---
+name: Cloud Issue
+about: Report an issue related to Reflex Cloud
+title: "[CLOUD] " # This acts as a hint, but users can change it.
+labels: cloud
+assignees: ""
+---
+
+## Describe the issue
+
+Provide details about the issue.
+
+...
+
+## Expected behavior
+
+What should have happened?
+
+...
+
+## Steps to reproduce (if applicable)
+
+1.
+2.
+3.
+
+## Environment
+
+- Reflex Version:
+- Python Version:
+- OS:
+- Browser:

+ 6 - 6
.github/ISSUE_TEMPLATE/custom_component_request.md

@@ -1,10 +1,9 @@
 ---
 name: Custom Component Request
 about: Suggest a new custom component for Reflex
-title: ''
-labels: 'custom component request'
-assignees: ''
-
+title: ""
+labels: "custom component request"
+assignees: ""
 ---
 
 **Describe the Custom Component**
@@ -17,7 +16,8 @@ A clear and concise description of what the custom component does.
 - What are the use cases for the custom component?
 
 **Specifics (please complete the following information):**
- - Do you have a specific react package in mind? (Optional):
- 
+
+- Do you have a specific react package in mind? (Optional):
+
 **Additional context**
 Add any other context about the custom component here.

+ 4 - 4
.github/ISSUE_TEMPLATE/enhancement_request.md

@@ -1,9 +1,9 @@
 ---
 name: Enhancement Request
 about: Suggest an enhancement for an existing Reflex feature.
-title: ''
-labels: 'enhancement'
-assignees: ''
+title: ""
+labels: "enhancement"
+assignees: ""
 ---
 
 **Describe the Enhancement you want**
@@ -14,6 +14,6 @@ A clear and concise description of what the improvement does.
 - What is the benefit of the enhancement?
 
 - Show an example/usecase were the improvement are needed.
- 
+
 **Additional context**
 Add any other context here.

+ 32 - 0
.github/ISSUE_TEMPLATE/enterprise_issue.md

@@ -0,0 +1,32 @@
+---
+name: Enterprise Issue
+about: Report an issue related to Reflex Enterprise
+title: "[ENTERPRISE] " # This acts as a hint, but users can change it.
+labels: enterprise
+assignees: ""
+---
+
+## Describe the issue
+
+Provide details about the issue.
+
+...
+
+## Expected behavior
+
+What should have happened?
+
+...
+
+## Steps to reproduce (if applicable)
+
+1.
+2.
+3.
+
+## Environment
+
+- Reflex Version:
+- Python Version:
+- OS:
+- Browser:

+ 4 - 5
.github/ISSUE_TEMPLATE/feature_request.md

@@ -1,10 +1,9 @@
 ---
 name: Feature Request
 about: Suggest a new feature for Reflex
-title: ''
-labels: 'feature request'
-assignees: ''
-
+title: ""
+labels: "feature request"
+assignees: ""
 ---
 
 **Describe the Features**
@@ -13,6 +12,6 @@ A clear and concise description of what the features does.
 - What is the purpose of the feature?
 
 - Show an example / use cases for the new feature.
- 
+
 **Additional context**
 Add any other context here.

+ 28 - 70
.github/actions/setup_build_env/action.yml

@@ -1,95 +1,59 @@
 # Entry conditions:
 # - `setup/checkout` has already happened
 # - working dir is the root directory of your project (e.g. `reflex/`).
-# - You have a `poetry.lock` file in the root directory of your project
+# - You have a `uv.lock` file in the root directory of your project
 # - You have a `pyproject.toml` file in the root directory of your project
 #
 # Exit conditions:
 # - Python of version `python-version` is ready to be invoked as `python`.
-# - Poetry of version `poetry-version` is ready to be invoked as `poetry`.
-# - If `run-poetry-install` is true, deps as defined in `pyproject.toml` will have been installed into the venv at `create-venv-at-path`.
+# - Uv of version `uv-version` is ready to be invoked as `uv`.
+# - If `run-uv-sync` is true, deps as defined in `pyproject.toml` will have been installed into the venv at `create-venv-at-path`.
 
-name: 'Setup Reflex build environment'
-description: 'Sets up Python, install poetry (cached), install project deps (cached)'
+name: "Setup Reflex build environment"
+description: "Sets up Python, install uv (cached), install project deps (cached)"
 inputs:
   python-version:
-    description: 'Python version setup'
+    description: "Python version setup"
     required: true
-  poetry-version:
-    description: 'Poetry version to install'
+  uv-version:
+    description: "Uv version to install"
     required: false
-    default: '1.8.3'
-  run-poetry-install:
-    description: 'Whether to run poetry install on current dir'
+    default: "0.6.9"
+  run-uv-sync:
+    description: "Whether to run uv sync on current dir"
     required: false
     default: false
   create-venv-at-path:
-    description: 'Path to venv (if poetry install is enabled)'
+    description: "Path to venv (if uv sync is enabled)"
     required: false
-    default: '.venv'
+    default: ".venv"
 
 runs:
-  using: 'composite'
+  using: "composite"
   steps:
-    - name: Set up Python ${{ inputs.python-version }}
-      uses: actions/setup-python@v5
+    - name: Install UV
+      uses: astral-sh/setup-uv@v5
       with:
+        version: ${{ inputs.uv-version }}
         python-version: ${{ inputs.python-version }}
-
-    # This is required for OS portability in presence of caching.
-    #
-    # The act of installing poetry has the side effect of adding
-    # poetry bin path to system path.
-    #
-    # But, if we get a cache hit on the poetry installation, we
-    # don't get this important side effect. As a result, bare calls
-    # to "poetry" fails.
-    - name: Prepare PATH env to include where poetry will be installed into
-      shell: bash
-      run: |
-        echo "~/.local/bin/" >> $GITHUB_PATH
-
-    - name: Restore cached poetry install
-      id: restore-poetry-cache
-      uses: actions/cache/restore@v4
-      with:
-        path: ~/.local
-        key: ${{ runner.os }}-python-${{ inputs.python-version }}-poetry-${{ inputs.poetry-version }}
-
-    - if: steps.restore-poetry-cache.outputs.cache-hit != 'true'
-      name: Install Poetry
-      uses: snok/install-poetry@v1
-      with:
-        version: ${{ inputs.poetry-version }}
-        virtualenvs-create: true
-        virtualenvs-in-project: true
-        virtualenvs-path: ${{ inputs.create-venv-at-path }}
-
-    - if: steps.restore-poetry-cache.outputs.cache-hit != 'true'
-      name: Save poetry install to cache
-      uses: actions/cache/save@v4
-      with:
-        path: ~/.local
-        key: ${{ steps.restore-poetry-cache.outputs.cache-primary-key }}
+        enable-cache: true
+        prune-cache: false
+        cache-dependency-glob: "uv.lock"
 
     - name: Restore cached project python deps
       id: restore-pydeps-cache
       uses: actions/cache/restore@v4
       with:
         path: ${{ inputs.create-venv-at-path }}
-        key: ${{ runner.os }}-python-${{ inputs.python-version }}-pydeps-${{ hashFiles('**/poetry.lock') }}
+        key: ${{ runner.os }}-python-${{ inputs.python-version }}-pydeps-${{ hashFiles('**/uv.lock') }}
 
-    - if: ${{ inputs.run-poetry-install == 'true' && steps.restore-pydeps-cache.outputs.cache-hit != 'true' }}
-      name: Run poetry install (will get cached)
+    - if: ${{ inputs.run-uv-sync == 'true' && steps.restore-pydeps-cache.outputs.cache-hit != 'true' }}
+      name: Run uv sync (will get cached)
       # We skip over installing the root package (the current project code under CI)
-      # Root package should not be cached - its content is not reflected in poetry.lock / cache key
-
-      # On Windows, it is scripts/activate. On Linux and MacOS, it is bin/activate
+      # Root package should not be cached - its content is not reflected in uv.lock / cache key
       shell: bash
       run: |
-        python -m venv ${{ inputs.create-venv-at-path }}
-        source ${{ inputs.create-venv-at-path }}/*/activate
-        poetry install --no-interaction --no-root
+        uv sync --all-extras --dev --no-install-project
 
     - if: steps.restore-pydeps-cache.outputs.cache-hit != 'true'
       name: Save Python deps to cache
@@ -98,16 +62,10 @@ runs:
         path: ${{ inputs.create-venv-at-path }}
         key: ${{ steps.restore-pydeps-cache.outputs.cache-primary-key }}
 
-    - if: ${{ inputs.run-poetry-install == 'true' }}
-      name: Run poetry install (root package)
+    - if: ${{ inputs.run-uv-sync == 'true' }}
+      name: Run uv sync (root package)
       # Here we really install the root package (the current project code under CI).env:
       # This should not be cached.
       shell: bash
       run: |
-        source ${{ inputs.create-venv-at-path }}/*/activate
-        poetry install --only-root --no-interaction
-
-    - name: Install uv
-      shell: bash
-      run: |
-        poetry run pip install uv
+        uv sync --all-extras --dev

+ 2 - 4
.github/pull_request_template.md

@@ -1,7 +1,7 @@
 ### All Submissions:
 
 - [ ] Have you followed the guidelines stated in [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) file?
-- [ ] Have you checked to ensure there aren't any other open [Pull Requests](https://github.com/reflex-dev/reflex/pulls ) for the desired changed?
+- [ ] Have you checked to ensure there aren't any other open [Pull Requests](https://github.com/reflex-dev/reflex/pulls) for the desired changed?
 
 <!-- You can erase any parts of this template not applicable to your Pull Request. -->
 
@@ -14,10 +14,9 @@ Please delete options that are not relevant.
 - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
 - [ ] This change requires a documentation update
 
-
 ### New Feature Submission:
 
-- [ ] Does your submission pass the tests? 
+- [ ] Does your submission pass the tests?
 - [ ] Have you linted your code locally prior to submission?
 
 ### Changes To Core Features:
@@ -33,4 +32,3 @@ Please delete options that are not relevant.
     b. Describe your changes.
 
     c. Put `closes #XXXX` in your comment to auto-close the issue that your PR fixes (if such).
-

+ 15 - 26
.github/workflows/benchmarks.yml

@@ -41,8 +41,7 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: ${{ matrix.python-version }}
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          run-uv-sync: true
 
       - name: Clone Reflex Website Repo
         uses: actions/checkout@v4
@@ -53,20 +52,20 @@ jobs:
 
       - name: Install Requirements for reflex-web
         working-directory: ./reflex-web
-        run: poetry run uv pip install -r requirements.txt
+        run: uv pip install -r requirements.txt
       - name: Init Website for reflex-web
         working-directory: ./reflex-web
-        run: poetry run reflex init
+        run: uv run reflex init
       - name: Install LightHouse Pre-reqs / Run LightHouse
         run: |
           # Check that npm is home
           npm -v
-          poetry run bash benchmarks/lighthouse.sh ./reflex-web prod
+          uv run bash benchmarks/lighthouse.sh ./reflex-web prod
         env:
           LHCI_GITHUB_APP_TOKEN: $
       - name: Run Benchmarks
         # Only run if the database creds are available in this context.
-        run: poetry run python benchmarks/benchmark_lighthouse.py "$GITHUB_SHA" ./integration/benchmarks/.lighthouseci
+        run: uv run python benchmarks/benchmark_lighthouse.py "$GITHUB_SHA" ./integration/benchmarks/.lighthouseci
         env:
           GITHUB_SHA: ${{ github.sha }}
 
@@ -82,15 +81,15 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: 3.12.8
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          run-uv-sync: true
+
       - name: Build reflex
         run: |
-          poetry build
+          uv build
       - name: Upload benchmark results
         # Only run if the database creds are available in this context.
         run:
-          poetry run python benchmarks/benchmark_package_size.py --os ubuntu-latest
+          uv run python benchmarks/benchmark_package_size.py --os ubuntu-latest
           --python-version 3.12.8 --commit-sha "${{ github.sha }}" --pr-id "${{ github.event.pull_request.id }}"
           --branch-name "${{ github.head_ref || github.ref_name }}"
           --path ./dist
@@ -114,29 +113,19 @@ jobs:
         uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
-      - name: Install Poetry
-        uses: snok/install-poetry@v1
+      - name: Install UV
+        uses: astral-sh/setup-uv@v5
         with:
-          version: 1.3.1
-          virtualenvs-create: true
-          virtualenvs-in-project: true
-          virtualenvs-path: .venv
-
-      - name: Run poetry install
-        shell: bash
-        run: |
-          python -m venv .venv
-          source .venv/*/activate
-          poetry install --without dev --no-interaction --no-root
+          version: 0.6.9
 
-      - name: Install uv
+      - name: Run uv sync
         shell: bash
         run: |
-          poetry run pip install uv
+          uv sync --no-install-project --no-dev
 
       - name: calculate and upload size
         run:
-          poetry run python benchmarks/benchmark_package_size.py --os "${{ matrix.os }}"
+          uv run python benchmarks/benchmark_package_size.py --os "${{ matrix.os }}"
           --python-version "${{ matrix.python-version }}" --commit-sha "${{ github.sha }}"
           --pr-id "${{ github.event.pull_request.id }}"
           --branch-name "${{ github.head_ref || github.ref_name }}"

+ 0 - 40
.github/workflows/check_generated_pyi.yml

@@ -1,40 +0,0 @@
-name: check-generated-pyi
-
-concurrency:
-  group: ${{ github.workflow }}-${{ github.event.pull_request.id }}
-  cancel-in-progress: true
-
-on:
-  push:
-    branches: ["main"]
-    # We don't just trigger on make_pyi.py and the components dir, because
-    # there are other things that can change the generator output
-    # e.g. black version, reflex.Component, reflex.Var.
-    paths-ignore:
-      - "**/*.md"
-  pull_request:
-    branches: ["main"]
-    paths-ignore:
-      - "**/*.md"
-
-jobs:
-  check-generated-pyi-components:
-    timeout-minutes: 30
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v4
-      - uses: ./.github/actions/setup_build_env
-        with:
-          python-version: "3.12.8"
-          run-poetry-install: true
-          create-venv-at-path: .venv
-      - run: |
-          poetry run python scripts/make_pyi.py
-          if [[ $(git status --porcelain) ]]; then
-            git status
-            git diff
-            echo "ERROR: make_pyi.py output is out of date. Please run scripts/make_pyi.py and commit the changes."
-            exit 1
-          else
-            echo "No diffs - AOK!"
-          fi

+ 7 - 8
.github/workflows/check_node_latest.yml

@@ -1,4 +1,6 @@
 name: integration-node-latest
+permissions:
+  contents: read
 
 on:
   push:
@@ -10,7 +12,6 @@ on:
 
 env:
   TELEMETRY_ENABLED: false
-  REFLEX_USE_SYSTEM_NODE: true
 
 jobs:
   check_latest_node:
@@ -27,14 +28,12 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: ${{ matrix.python-version }}
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          run-uv-sync: true
+
       - uses: actions/setup-node@v4
         with:
           node-version: ${{ matrix.node-version }}
+      - run: uv run playwright install --with-deps
       - run: |
-          poetry run uv pip install pyvirtualdisplay pillow pytest-split
-          poetry run playwright install --with-deps
-      - run: |
-          poetry run pytest tests/test_node_version.py
-          poetry run pytest tests/integration --splits 2 --group ${{matrix.split_index}}
+          uv run pytest tests/test_node_version.py
+          uv run pytest tests/integration --splits 2 --group ${{matrix.split_index}}

+ 10 - 11
.github/workflows/check_outdated_dependencies.yml

@@ -1,4 +1,6 @@
 name: check-outdated-dependencies
+permissions:
+  contents: read
 
 on:
   push: # This will trigger the action when a pull request is opened or updated.
@@ -16,13 +18,12 @@ jobs:
 
       - uses: ./.github/actions/setup_build_env
         with:
-          python-version: '3.10'
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          python-version: "3.10"
+          run-uv-sync: true
 
       - name: Check outdated backend dependencies
         run: |
-          outdated=$(poetry show -oT)
+          outdated=$(uv pip list --outdated)
           echo "Outdated:"
           echo "$outdated"
 
@@ -45,8 +46,8 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: "3.10.16"
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          run-uv-sync: true
+
       - name: Clone Reflex Website Repo
         uses: actions/checkout@v4
         with:
@@ -55,15 +56,13 @@ jobs:
           path: reflex-web
       - name: Install Requirements for reflex-web
         working-directory: ./reflex-web
-        run: poetry run uv pip install $(grep -ivE "reflex " requirements.txt)
-      - name: Install additional dependencies for DB access
-        run: poetry run uv pip install psycopg
+        run: uv pip install $(grep -ivE "reflex " requirements.txt)
       - name: Init Website for reflex-web
         working-directory: ./reflex-web
-        run: poetry run reflex init
+        run: uv run reflex init
       - name: Run Website and Check for errors
         run: |
-          poetry run bash scripts/integration.sh ./reflex-web dev
+          uv run bash scripts/integration.sh ./reflex-web dev
       - name: Check outdated frontend dependencies
         working-directory: ./reflex-web/.web
         run: |

+ 4 - 4
.github/workflows/dependency-review.yml

@@ -1,4 +1,4 @@
-name: 'Dependency Review'
+name: "Dependency Review"
 on: [pull_request]
 
 permissions:
@@ -8,10 +8,10 @@ jobs:
   dependency-review:
     runs-on: ubuntu-latest
     steps:
-      - name: 'Checkout Repository'
+      - name: "Checkout Repository"
         uses: actions/checkout@v4
-      - name: 'Dependency Review'
+      - name: "Dependency Review"
         uses: actions/dependency-review-action@v4
         with:
           allow-licenses: Apache-2.0, BSD-2-Clause, BSD-3-Clause, HPND, ISC, MIT, MPL-2.0, Unlicense, Python-2.0, Python-2.0.1, Apache-2.0 AND MIT, BSD-2-Clause AND BSD-3-Clause, Apache-2.0 AND BSD-3-Clause
-          allow-dependencies-licenses: 'pkg:pypi/lazy-loader'
+          allow-dependencies-licenses: "pkg:pypi/lazy-loader"

+ 6 - 5
.github/workflows/integration_app_harness.yml

@@ -13,6 +13,8 @@ on:
     branches: ["main"]
     paths-ignore:
       - "**/*.md"
+env:
+  APP_HARNESS_HEADLESS: 1
 
 permissions:
   contents: read
@@ -45,12 +47,11 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: ${{ matrix.python-version }}
-          run-poetry-install: true
-          create-venv-at-path: .venv
-      - run: poetry run uv pip install pyvirtualdisplay pillow pytest-split pytest-retry
+          run-uv-sync: true
+
       - name: Run app harness tests
         env:
           REDIS_URL: ${{ matrix.state_manager == 'redis' && 'redis://localhost:6379' || '' }}
         run: |
-          poetry run playwright install chromium
-          poetry run pytest tests/integration --retries 3 --maxfail=5 --splits 2 --group ${{matrix.split_index}}
+          uv run playwright install chromium
+          uv run pytest tests/integration --retries 3 --maxfail=5 --splits 2 --group ${{matrix.split_index}}

+ 29 - 39
.github/workflows/integration_tests.yml

@@ -43,17 +43,17 @@ jobs:
       matrix:
         # Show OS combos first in GUI
         os: [ubuntu-latest, windows-latest]
-        python-version: ['3.10.16', '3.11.11', '3.12.8', '3.13.1']
+        python-version: ["3.10.16", "3.11.11", "3.12.8", "3.13.1"]
         exclude:
           - os: windows-latest
             python-version: "3.11.11"
           - os: windows-latest
-            python-version: '3.10.16'
+            python-version: "3.10.16"
         include:
           - os: windows-latest
             python-version: "3.11.9"
           - os: windows-latest
-            python-version: '3.10.11'
+            python-version: "3.10.11"
 
     runs-on: ${{ matrix.os }}
     steps:
@@ -61,8 +61,8 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: ${{ matrix.python-version }}
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          run-uv-sync: true
+
       - name: Clone Reflex Examples Repo
         uses: actions/checkout@v4
         with:
@@ -71,49 +71,44 @@ jobs:
       - name: Install requirements for counter example
         working-directory: ./reflex-examples/counter
         run: |
-          poetry run uv pip install -r requirements.txt
-      - name: Install additional dependencies for DB access
-        run: poetry run uv pip install psycopg
+          uv pip install -r requirements.txt
       - name: Check export --backend-only before init for counter example
         working-directory: ./reflex-examples/counter
         run: |
-          poetry run reflex export --backend-only
+          uv run reflex export --backend-only
       - name: Check run --backend-only before init for counter example
         run: |
-          poetry run bash scripts/integration.sh ./reflex-examples/counter dev 8001 --backend-only --backend-port 8001
+          uv run bash scripts/integration.sh ./reflex-examples/counter dev 8001 --backend-only --backend-port 8001
       - name: Init Website for counter example
         working-directory: ./reflex-examples/counter
         run: |
-          poetry run reflex init --loglevel debug
+          uv run reflex init --loglevel debug
       - name: Check export for counter example
         working-directory: ./reflex-examples/counter
         run: |
-          poetry run reflex export
+          uv run reflex export
       - name: Run Website and Check for errors
         run: |
           # Check that npm is home
           npm -v
-          poetry run bash scripts/integration.sh ./reflex-examples/counter dev
+          uv run bash scripts/integration.sh ./reflex-examples/counter dev
       - name: Install requirements for nba proxy example
         working-directory: ./reflex-examples/nba-proxy
         run: |
-          poetry run uv pip install -r requirements.txt
-      - name: Install additional dependencies for DB access
-        run: poetry run uv pip install psycopg
+          uv pip install -r requirements.txt
       - name: Check export --backend-only before init for nba-proxy example
         working-directory: ./reflex-examples/nba-proxy
         run: |
-          poetry run reflex export --backend-only
+          uv run reflex export --backend-only
       - name: Init Website for nba-proxy example
         working-directory: ./reflex-examples/nba-proxy
         run: |
-          poetry run reflex init --loglevel debug
+          uv run reflex init --loglevel debug
       - name: Run Website and Check for errors
         run: |
           # Check that npm is home
           npm -v
-          poetry run bash scripts/integration.sh ./reflex-examples/nba-proxy dev
-
+          uv run bash scripts/integration.sh ./reflex-examples/nba-proxy dev
 
   reflex-web:
     strategy:
@@ -131,8 +126,7 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: ${{ matrix.python-version }}
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          run-uv-sync: true
 
       - name: Clone Reflex Website Repo
         uses: actions/checkout@v4
@@ -143,17 +137,15 @@ jobs:
 
       - name: Install Requirements for reflex-web
         working-directory: ./reflex-web
-        run: poetry run uv pip install $(grep -ivE "reflex " requirements.txt)
-      - name: Install additional dependencies for DB access
-        run: poetry run uv pip install psycopg
+        run: uv pip install $(grep -ivE "reflex " requirements.txt)
       - name: Init Website for reflex-web
         working-directory: ./reflex-web
-        run: poetry run reflex init
+        run: uv run reflex init
       - name: Run Website and Check for errors
         run: |
           # Check that npm is home
           npm -v
-          poetry run bash scripts/integration.sh ./reflex-web prod
+          uv run bash scripts/integration.sh ./reflex-web prod
 
   rx-shout-from-template:
     strategy:
@@ -164,24 +156,24 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: "3.11.11"
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          run-uv-sync: true
+
       - name: Create app directory
         run: mkdir rx-shout-from-template
       - name: Init reflex-web from template
-        run: poetry run reflex init --template https://github.com/masenf/rx_shout
+        run: uv run reflex init --template https://github.com/masenf/rx_shout
         working-directory: ./rx-shout-from-template
       - name: ignore reflex pin in requirements
         run: sed -i -e '/reflex==/d' requirements.txt
         working-directory: ./rx-shout-from-template
       - name: Install additional dependencies
-        run: poetry run uv pip install -r requirements.txt
+        run: uv pip install -r requirements.txt
         working-directory: ./rx-shout-from-template
       - name: Run Website and Check for errors
         run: |
           # Check that npm is home
           npm -v
-          poetry run bash scripts/integration.sh ./rx-shout-from-template prod
+          uv run bash scripts/integration.sh ./rx-shout-from-template prod
 
   reflex-web-macos:
     if: github.event_name == 'push' && github.ref == 'refs/heads/main'
@@ -196,8 +188,8 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: ${{ matrix.python-version }}
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          run-uv-sync: true
+
       - name: Clone Reflex Website Repo
         uses: actions/checkout@v4
         with:
@@ -206,14 +198,12 @@ jobs:
           path: reflex-web
       - name: Install Requirements for reflex-web
         working-directory: ./reflex-web
-        run: poetry run uv pip install -r requirements.txt
-      - name: Install additional dependencies for DB access
-        run: poetry run uv pip install psycopg
+        run: uv pip install -r requirements.txt
       - name: Init Website for reflex-web
         working-directory: ./reflex-web
-        run: poetry run reflex init
+        run: uv run reflex init
       - name: Run Website and Check for errors
         run: |
           # Check that npm is home
           npm -v
-          poetry run bash scripts/integration.sh ./reflex-web prod
+          uv run bash scripts/integration.sh ./reflex-web prod

+ 20 - 30
.github/workflows/integration_tests_wsl.yml

@@ -6,28 +6,25 @@ concurrency:
 
 on:
   push:
-    branches: ['main']
+    branches: ["main"]
     paths-ignore:
-      - '**/*.md'
+      - "**/*.md"
   pull_request:
-    branches: ['main']
+    branches: ["main"]
     paths-ignore:
-      - '**/*.md'
+      - "**/*.md"
 
 permissions:
   contents: read
 
 env:
   TELEMETRY_ENABLED: false
-  NODE_OPTIONS: '--max_old_space_size=4096'
+  NODE_OPTIONS: "--max_old_space_size=4096"
 
 jobs:
   example-counter-wsl:
-    timeout-minutes: 30
-    # 2019 is more stable with WSL in GH actions
-    # https://github.com/actions/runner-images/issues/5151
-    # Confirmed through trial and error. 2022 has >80% failure rate (probably BSOD)
-    runs-on: windows-2019
+    timeout-minutes: 20
+    runs-on: windows-latest
     steps:
       - uses: actions/checkout@v4
       - name: Clone Reflex Examples Repo
@@ -36,64 +33,57 @@ jobs:
           repository: reflex-dev/reflex-examples
           path: reflex-examples
 
-      - uses: Vampire/setup-wsl@v3
+      - uses: Vampire/setup-wsl@v5
         with:
           distribution: Ubuntu-24.04
 
-      - name: Install Python
+      - name: Install packages
         shell: wsl-bash {0}
         run: |
-          apt update
-          apt install -y python3 python3-pip curl dos2unix zip unzip
+          sudo apt-get update
+          sudo apt-get install -y python3 python3-pip curl dos2unix zip unzip
 
-      - name: Install Poetry
+      - name: Install Uv
         shell: wsl-bash {0}
         run: |
-          curl -sSL https://install.python-poetry.org | python3 -
-          # Symlink seems easier to make work than persisting PATH changes, in WSL
-          ln -s /root/.local/bin/poetry /usr/local/bin/poetry
+          curl -LsSf https://astral.sh/uv/install.sh | sh
 
       - name: Install reflex deps
         shell: wsl-bash {0}
         run: |
-          poetry install
-
-      - name: Install uv
-        shell: wsl-bash {0}
-        run: |
-          poetry run pip install uv
+          /root/.local/bin/uv sync --link-mode=copy
 
       - name: Install requirements for counter example
         working-directory: ./reflex-examples/counter
         shell: wsl-bash {0}
         run: |
-          poetry run uv pip install -r requirements.txt
+          /root/.local/bin/uv pip install -r requirements.txt --link-mode=copy
       - name: Check export --backend-only before init for counter example
         working-directory: ./reflex-examples/counter
         shell: wsl-bash {0}
         run: |
           export TELEMETRY_ENABLED=false
-          poetry run reflex export --backend-only
+          /root/.local/bin/uv run reflex export --backend-only
       - name: Check run --backend-only before init for counter example
         shell: wsl-bash {0}
         run: |
           export TELEMETRY_ENABLED=false
           dos2unix scripts/integration.sh
-          poetry run bash scripts/integration.sh ./reflex-examples/counter dev 8001 --backend-only --backend-port 8001
+          /root/.local/bin/uv run bash scripts/integration.sh ./reflex-examples/counter dev 8001 --backend-only --backend-port 8001
       - name: Init Website for counter example
         working-directory: ./reflex-examples/counter
         shell: wsl-bash {0}
         run: |
           export TELEMETRY_ENABLED=false
-          poetry run reflex init --loglevel debug
+          /root/.local/bin/uv run reflex init --loglevel debug
       - name: Check export for counter example
         working-directory: ./reflex-examples/counter
         shell: wsl-bash {0}
         run: |
           export TELEMETRY_ENABLED=false
-          poetry run reflex export --frontend-only --loglevel debug
+          /root/.local/bin/uv run reflex export --frontend-only --loglevel debug
       - name: Run Website and Check for errors
         shell: wsl-bash {0}
         run: |
           export TELEMETRY_ENABLED=false
-          poetry run bash scripts/integration.sh ./reflex-examples/counter dev
+          /root/.local/bin/uv run bash scripts/integration.sh ./reflex-examples/counter dev

+ 14 - 5
.github/workflows/performance.yml

@@ -1,4 +1,6 @@
 name: performance-tests
+permissions:
+  contents: read
 
 on:
   push:
@@ -22,13 +24,20 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
-      - uses: ./.github/actions/setup_build_env
+
+      - name: Install uv
+        uses: astral-sh/setup-uv@v5
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
         with:
-          python-version: 3.12.8
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          python-version: "3.12.8"
+
+      - name: Install dependencies
+        run: uv sync --all-extras --dev
+
       - name: Run benchmarks
         uses: CodSpeedHQ/action@v3
         with:
           token: ${{ secrets.CODSPEED_TOKEN }}
-          run: poetry run pytest tests/benchmarks --codspeed
+          run: uv run pytest tests/benchmarks --codspeed

+ 8 - 11
.github/workflows/pre-commit.yml

@@ -1,4 +1,6 @@
 name: pre-commit
+permissions:
+  contents: read
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.event.pull_request.id }}
@@ -21,14 +23,9 @@ jobs:
       - uses: actions/checkout@v4
       - uses: ./.github/actions/setup_build_env
         with:
-          # running vs. one version of Python is OK
-          # i.e. ruff, black, etc.
-          python-version: 3.12.8
-          run-poetry-install: true
-          create-venv-at-path: .venv
-      # TODO pre-commit related stuff can be cached too (not a bottleneck yet)
-      - run: |
-          poetry run uv pip install pre-commit
-          poetry run pre-commit run --all-files
-        env:
-          SKIP: update-pyi-files
+          python-version: 3.13.2
+          run-uv-sync: true
+      - uses: actions/checkout@v4
+        with:
+          clean: false
+      - run: uv run pre-commit run --all-files --show-diff-on-failure

+ 6 - 4
.github/workflows/reflex_init_in_docker_test.yml

@@ -1,4 +1,6 @@
 name: reflex-init-in-docker-test
+permissions:
+  contents: read
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.event.pull_request.id }}
@@ -6,13 +8,13 @@ concurrency:
 
 on:
   push:
-    branches: ['main']
+    branches: ["main"]
     paths-ignore:
-      - '**/*.md'
+      - "**/*.md"
   pull_request:
-    branches: ['main']
+    branches: ["main"]
     paths-ignore:
-      - '**/*.md'
+      - "**/*.md"
 
 jobs:
   # TODO we can extend to various starting points (e.g. Ubuntu with node, without node, with unzip, without unzip, etc.)

+ 12 - 12
.github/workflows/unit_tests.yml

@@ -61,26 +61,26 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: ${{ matrix.python-version }}
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          run-uv-sync: true
+
       - name: Run unit tests
         run: |
           export PYTHONUNBUFFERED=1
-          poetry run pytest tests/units --cov --no-cov-on-fail --cov-report=
+          uv 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/units --cov --no-cov-on-fail --cov-report=
+          uv 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/units --cov --no-cov-on-fail --cov-report=
+          uv pip install "pydantic~=1.10"
+          uv run pytest tests/units --cov --no-cov-on-fail --cov-report=
       - name: Generate coverage report
-        run: poetry run coverage html
+        run: uv run coverage html
 
   unit-tests-macos:
     timeout-minutes: 30
@@ -96,14 +96,14 @@ jobs:
       - uses: ./.github/actions/setup_build_env
         with:
           python-version: ${{ matrix.python-version }}
-          run-poetry-install: true
-          create-venv-at-path: .venv
+          run-uv-sync: true
+
       - name: Run unit tests
         run: |
           export PYTHONUNBUFFERED=1
-          poetry run pytest tests/units --cov --no-cov-on-fail --cov-report=
+          uv run pytest tests/units --cov --no-cov-on-fail --cov-report=
       - name: Run unit tests w/ pydantic v1
         run: |
           export PYTHONUNBUFFERED=1
-          poetry run uv pip install "pydantic~=1.10"
-          poetry run pytest tests/units --cov --no-cov-on-fail --cov-report=
+          uv pip install "pydantic~=1.10"
+          uv run pytest tests/units --cov --no-cov-on-fail --cov-report=

+ 6 - 1
.gitignore

@@ -15,4 +15,9 @@ requirements.txt
 .pyi_generator_last_run
 .pyi_generator_diff
 reflex.db
-.codspeed
+.codspeed
+.env
+.env.*
+node_modules
+package-lock.json
+*.pyi

+ 13 - 8
.pre-commit-config.yaml

@@ -1,21 +1,22 @@
 fail_fast: true
 
 repos:
-
   - repo: https://github.com/charliermarsh/ruff-pre-commit
-    rev: v0.9.6
+    rev: v0.11.2
     hooks:
       - id: ruff-format
         args: [reflex, tests]
       - id: ruff
         args: ["--fix", "--exit-non-zero-on-fix"]
-        exclude: '^integration/benchmarks/'
+        exclude: "^integration/benchmarks/"
 
   - repo: https://github.com/codespell-project/codespell
-    rev: v2.3.0
+    rev: v2.4.1
     hooks:
       - id: codespell
         args: ["reflex"]
+        additional_dependencies:
+          - tomli
 
   # Run pyi check before pyright because pyright can fail if pyi files are wrong.
   - repo: local
@@ -25,11 +26,11 @@ repos:
         always_run: true
         language: system
         require_serial: true
-        description: 'Update pyi files as needed'
+        description: "Update pyi files as needed"
         entry: python3 scripts/make_pyi.py
 
   - repo: https://github.com/RobertCraigie/pyright-python
-    rev: v1.1.393
+    rev: v1.1.398
     hooks:
       - id: pyright
         args: [reflex, tests]
@@ -39,5 +40,9 @@ repos:
     rev: v1.8.1
     hooks:
       - id: darglint
-        exclude: '^reflex/reflex.py'
-
+        exclude: "^reflex/reflex.py"
+  - repo: https://github.com/pre-commit/mirrors-prettier
+    rev: f62a70a3a7114896b062de517d72829ea1c884b6
+    hooks:
+      - id: prettier
+        require_serial: true

+ 11 - 11
CODE_OF_CONDUCT.md

@@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
 Examples of behavior that contributes to a positive environment for our
 community include:
 
-* Demonstrating empathy and kindness toward other people
-* Being respectful of differing opinions, viewpoints, and experiences
-* Giving and gracefully accepting constructive feedback
-* Accepting responsibility and apologizing to those affected by our mistakes,
+- Demonstrating empathy and kindness toward other people
+- Being respectful of differing opinions, viewpoints, and experiences
+- Giving and gracefully accepting constructive feedback
+- Accepting responsibility and apologizing to those affected by our mistakes,
   and learning from the experience
-* Focusing on what is best not just for us as individuals, but for the
+- Focusing on what is best not just for us as individuals, but for the
   overall community
 
 Examples of unacceptable behavior include:
 
-* The use of sexualized language or imagery, and sexual attention or
+- The use of sexualized language or imagery, and sexual attention or
   advances of any kind
-* Trolling, insulting or derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or email
+- Trolling, insulting or derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or email
   address, without their explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
+- Other conduct which could reasonably be considered inappropriate in a
   professional setting
 
 ## Enforcement Responsibilities
@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
 ### 4. Permanent Ban
 
 **Community Impact**: Demonstrating a pattern of violation of community
-standards, including sustained inappropriate behavior,  harassment of an
+standards, including sustained inappropriate behavior, harassment of an
 individual, or aggression toward or disparagement of classes of individuals.
 
 **Consequence**: A permanent ban from any sort of public interaction within

+ 21 - 24
CONTRIBUTING.md

@@ -8,39 +8,38 @@ Here is a quick guide on how to run Reflex repo locally so you can start contrib
 
 **Prerequisites:**
 
-- Python >= 3.10
-- Poetry version >= 1.4.0 and add it to your path (see [Poetry Docs](https://python-poetry.org/docs/#installation) for more info).
+- uv version >= 0.6.0 and add it to your path (see [UV Docs](https://docs.astral.sh/uv/getting-started/installation/) for more info).
 
 **1. Fork this repository:**
 Fork this repository by clicking on the `Fork` button on the top right.
 
 **2. Clone Reflex and navigate into the repo:**
 
-``` bash
+```bash
 git clone https://github.com/<YOUR-USERNAME>/reflex.git
 cd reflex
 ```
 
 **3. Install your local Reflex build:**
 
-``` bash
-poetry install
+```bash
+uv sync --python 3.13
 ```
 
 **4. Now create an examples folder so you can test the local Python build in this repository.**
 
 - We have the `examples` folder in the `.gitignore`, so your changes in `reflex/examples` won't be reflected in your commit.
 
-``` bash
+```bash
 mkdir examples
 cd examples
 ```
 
 **5. Init and Run**
 
-``` bash
-poetry run reflex init
-poetry run reflex run
+```bash
+uv run reflex init
+uv run reflex run
 ```
 
 All the changes you make to the repository will be reflected in your running app.
@@ -68,35 +67,34 @@ Before submitting, a pull request, ensure the following steps are taken and test
 In your `reflex` directory run make sure all the unit tests are still passing using the following command.
 This will fail if code coverage is below 70%.
 
-``` bash
-poetry run pytest tests/units --cov --no-cov-on-fail --cov-report= 
+```bash
+uv 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.
 
-``` bash
-poetry run ruff check .
-poetry run pyright reflex tests
-find reflex tests -name "*.py" -not -path reflex/reflex.py | xargs poetry run darglint
+```bash
+uv run ruff check .
+uv run pyright reflex tests
+find reflex tests -name "*.py" -not -path reflex/reflex.py | xargs uv run darglint
 ```
 
 Finally, run `ruff` to format your code.
 
-``` bash
-poetry run ruff format .
+```bash
+uv run ruff format .
 ```
 
 Consider installing git pre-commit hooks so Ruff, Pyright, Darglint and `make_pyi` will run automatically before each commit.
 Note that pre-commit will only be installed when you use a Python version >= 3.10.
 
-``` bash
+```bash
 pre-commit install
 ```
 
 That's it you can now submit your PR. Thanks for contributing to Reflex!
 
-
-## Editing Templates 
+## Editing Templates
 
 To edit the templates in Reflex you can do so in two way.
 
@@ -104,13 +102,12 @@ Change to the basic `blank` template can be done in the `reflex/.templates/apps/
 
 Others templates can be edited in their own repository. For example the `sidebar` template can be found in the [`reflex-sidebar`](https://github.com/reflex-dev/sidebar-template) repository.
 
-
 ## Other Notes
 
 For some pull requests when adding new components you will have to generate a pyi file for the new component. This is done by running the following command in the `reflex` directory.
 
 (Please check in with the team before adding a new component to Reflex we are cautious about adding new components to Reflex's core.)
 
-``` bash
-poetry run python scripts/make_pyi.py 
-```
+```bash
+uv run python scripts/make_pyi.py
+```

+ 14 - 20
README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
@@ -6,10 +5,13 @@
 <hr>
 
 ### **✨ Performant, customizable web apps in pure Python. Deploy in seconds. ✨**
+
 [![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)
 ![versions](https://img.shields.io/pypi/pyversions/reflex.svg)
 [![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)
+[![PyPI Downloads](https://static.pepy.tech/badge/reflex)](https://pepy.tech/projects/reflex)
 [![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)
+
 </div>
 
 ---
@@ -23,9 +25,10 @@
 Reflex is a library to build full-stack web apps in pure Python.
 
 Key features:
-* **Pure Python** - Write your app's frontend and backend all in Python, no need to learn Javascript.
-* **Full Flexibility** - Reflex is easy to get started with, but can also scale to complex apps.
-* **Deploy Instantly** - After building, deploy your app with a [single command](https://reflex.dev/docs/hosting/deploy-quick-start/) or host it on your own server.
+
+- **Pure Python** - Write your app's frontend and backend all in Python, no need to learn Javascript.
+- **Full Flexibility** - Reflex is easy to get started with, but can also scale to complex apps.
+- **Deploy Instantly** - After building, deploy your app with a [single command](https://reflex.dev/docs/hosting/deploy-quick-start/) or host it on your own server.
 
 See our [architecture page](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) to learn how Reflex works under the hood.
 
@@ -49,7 +52,7 @@ cd my_app_name
 reflex init
 ```
 
-This command initializes a template app in your new directory. 
+This command initializes a template app in your new directory.
 
 You can run this app in development mode:
 
@@ -61,7 +64,6 @@ You should see your app running at http://localhost:3000.
 
 Now you can modify the source code in `my_app_name/my_app_name.py`. Reflex has fast refreshes so you can see your changes instantly when you save your code.
 
-
 ## 🫧 Example App
 
 Let's go over an example: creating an image generation UI around [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node). For simplicity, we just call the [OpenAI API](https://platform.openai.com/docs/api-reference/authentication), but you could replace this with an ML model run locally.
@@ -76,8 +78,6 @@ Let's go over an example: creating an image generation UI around [DALL·E](https
 
 Here is the complete code to create this. This is all done in one Python file!
 
-
-  
 ```python
 import reflex as rx
 import openai
@@ -117,7 +117,7 @@ def index():
                 width="25em",
             ),
             rx.button(
-                "Generate Image", 
+                "Generate Image",
                 on_click=State.get_image,
                 width="25em",
                 loading=State.processing
@@ -137,17 +137,12 @@ app = rx.App()
 app.add_page(index, title="Reflex:DALL-E")
 ```
 
-
-
-
-
 ## Let's break this down.
 
 <div align="center">
 <img src="docs/images/dalle_colored_code_example.png" alt="Explaining the differences between backend and frontend parts of the DALL-E app." width="900" />
 </div>
 
-
 ### **Reflex UI**
 
 Let's start with the UI.
@@ -225,11 +220,10 @@ You can create a multi-page app by adding more pages.
 
 <div align="center">
 
-📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; |  &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start)  &nbsp;   
+📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
 
 </div>
 
-
 ## ✅ Status
 
 Reflex launched in December 2022 with the name Pynecone.
@@ -242,14 +236,14 @@ Reflex has new releases and features coming every other week! Make sure to :star
 
 We welcome contributions of any size! Below are some good ways to get started in the Reflex community.
 
--   **Join Our Discord**: Our [Discord](https://discord.gg/T5WSbC2YtQ) is the best place to get help on your Reflex project and to discuss how you can contribute.
--   **GitHub Discussions**: A great way to talk about features you want added or things that are confusing/need clarification.
--   **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues) are an excellent way to report bugs. Additionally, you can try and solve an existing issue and submit a PR.
+- **Join Our Discord**: Our [Discord](https://discord.gg/T5WSbC2YtQ) is the best place to get help on your Reflex project and to discuss how you can contribute.
+- **GitHub Discussions**: A great way to talk about features you want added or things that are confusing/need clarification.
+- **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues) are an excellent way to report bugs. Additionally, you can try and solve an existing issue and submit a PR.
 
 We are actively looking for contributors, no matter your skill level or experience. To contribute check out [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
 
-
 ## All Thanks To Our Contributors:
+
 <a href="https://github.com/reflex-dev/reflex/graphs/contributors">
   <img src="https://contrib.rocks/image?repo=reflex-dev/reflex" />
 </a>

+ 3 - 3
SECURITY.md

@@ -2,9 +2,9 @@
 
 ## Supported Versions
 
-| Version    | Supported          |
-| ---------- | ------------------ |
-| >= 0.1.18   | :white_check_mark: |
+| Version   | Supported          |
+| --------- | ------------------ |
+| >= 0.1.18 | :white_check_mark: |
 
 ## Reporting a Vulnerability
 

+ 1 - 1
docker-example/README.md

@@ -27,4 +27,4 @@ database.
 
 This example deployment is intended for use with App hosting platforms, like
 Azure, AWS, or Google Cloud Run. It is the backend of the deployment, which
-depends on a separately hosted redis instance and static frontend deployment.
+depends on a separately hosted redis instance and static frontend deployment.

+ 24 - 23
docker-example/production-app-platform/README.md

@@ -6,12 +6,13 @@ Azure, AWS, or Google Cloud Run.
 ## Architecture
 
 The production deployment consists of a few pieces:
-  * Backend container - built by `Dockerfile` Runs the Reflex backend
-    service on port 8000 and is scalable to multiple instances.
-  * Redis container - A single instance the standard `redis` docker image should
-    share private networking with the backend
-  * Static frontend - HTML/CSS/JS files that are hosted via a CDN or static file
-    server. This is not included in the docker image.
+
+- Backend container - built by `Dockerfile` Runs the Reflex backend
+  service on port 8000 and is scalable to multiple instances.
+- Redis container - A single instance the standard `redis` docker image should
+  share private networking with the backend
+- Static frontend - HTML/CSS/JS files that are hosted via a CDN or static file
+  server. This is not included in the docker image.
 
 ## Deployment
 
@@ -37,7 +38,7 @@ the redis service.
 
 ### Ingress
 
-Configure the load balancer for the app to forward traffic to port 8000 on the 
+Configure the load balancer for the app to forward traffic to port 8000 on the
 backend service replicas. Most platforms will generate an ingress hostname
 automatically. Make sure when you access the ingress endpoint on `/ping` that it
 returns "pong", indicating that the backend is up an available.
@@ -95,19 +96,19 @@ container volume. Use Azure Files and mount it into the container at /app/upload
 
 #### Resource Types
 
-* Create a new vnet with 10.0.0.0/16
-  * Create a new subnet for redis, database, and containers
-* Deploy redis as a Container Instances
-* Deploy database server as "Azure Database for PostgreSQL"
-  * Create a new database for the app
-  * Set db-url as a secret containing the db user/password connection string
-* Deploy Storage account for uploaded files
-  * Enable access from the vnet and container subnet
-  * Create a new file share
-  * In the environment, create a new files share (get the storage key)
-* Deploy the backend as a Container App
-  * Create a custom Container App Environment linked up to the same vnet as the redis container.
-  * Set REDIS_URL and DB_URL environment variables
-  * Add the volume from the environment
-  * Add the volume mount to the container
-* Deploy the frontend as a Static Web App
+- Create a new vnet with 10.0.0.0/16
+  - Create a new subnet for redis, database, and containers
+- Deploy redis as a Container Instances
+- Deploy database server as "Azure Database for PostgreSQL"
+  - Create a new database for the app
+  - Set db-url as a secret containing the db user/password connection string
+- Deploy Storage account for uploaded files
+  - Enable access from the vnet and container subnet
+  - Create a new file share
+  - In the environment, create a new files share (get the storage key)
+- Deploy the backend as a Container App
+  - Create a custom Container App Environment linked up to the same vnet as the redis container.
+  - Set REDIS_URL and DB_URL environment variables
+  - Add the volume from the environment
+  - Add the volume mount to the container
+- Deploy the frontend as a Static Web App

+ 2 - 2
docker-example/production-compose/README.md

@@ -25,7 +25,7 @@ If the app uses additional backend API routes, those should be added to the
 ## Build Reflex Production Service
 
 During build, set `DOMAIN` environment variable to the domain where the app will
-be hosted!  (Do not include http or https, it will always use https).
+be hosted! (Do not include http or https, it will always use https).
 
 **If `DOMAIN` is not provided, the service will default to `localhost`.**
 
@@ -72,4 +72,4 @@ to deploy these services if they are not in active use.
 
 ```bash
 DOMAIN=example.com docker compose -f compose.yaml -f compose.prod.yaml -f compose.tools.yaml up -d
-```
+```

+ 2 - 2
docker-example/production-compose/compose.prod.yaml

@@ -7,7 +7,7 @@ services:
     environment:
       POSTGRES_PASSWORD: secret
     volumes:
-       - postgres-data:/var/lib/postgresql/data
+      - postgres-data:/var/lib/postgresql/data
 
   redis:
     image: redis
@@ -22,4 +22,4 @@ services:
       - redis
 
 volumes:
-  postgres-data:
+  postgres-data:

+ 2 - 2
docker-example/production-compose/compose.tools.yaml

@@ -10,9 +10,9 @@ services:
   redis-commander:
     image: ghcr.io/joeferner/redis-commander:latest
     environment:
-    - REDIS_HOSTS=local:redis:6379
+      - REDIS_HOSTS=local:redis:6379
     ports:
-    - "8081:8081"
+      - "8081:8081"
 
 volumes:
   redis-ui-settings:

+ 5 - 5
docker-example/production-compose/compose.yaml

@@ -13,8 +13,8 @@ services:
     build:
       context: .
     volumes:
-       - db-data:/app/data
-       - upload-data:/app/uploaded_files
+      - db-data:/app/data
+      - upload-data:/app/uploaded_files
     restart: always
 
   webserver:
@@ -22,12 +22,12 @@ services:
       DOMAIN: ${DOMAIN:-localhost}
     ports:
       - 443:443
-      - 80:80  # For acme-challenge via HTTP.
+      - 80:80 # For acme-challenge via HTTP.
     build:
       context: .
       dockerfile: Caddy.Dockerfile
     volumes:
-       - caddy-data:/root/.caddy
+      - caddy-data:/root/.caddy
     restart: always
     depends_on:
       - app
@@ -38,4 +38,4 @@ volumes:
   # Uploaded files
   upload-data:
   # TLS keys and certificates
-  caddy-data:
+  caddy-data:

+ 1 - 1
docker-example/production-one-port/Dockerfile

@@ -21,7 +21,7 @@ WORKDIR /app
 COPY requirements.txt .
 RUN pip install -r requirements.txt
 
-# Install reflex helper utilities like bun/fnm/node
+# Install reflex helper utilities like bun/node
 COPY rxconfig.py ./
 RUN reflex init
 

+ 6 - 4
docker-example/production-one-port/README.md

@@ -1,13 +1,15 @@
 # production-one-port
 
 This docker deployment runs Reflex in prod mode, exposing a single HTTP port:
-  * `8080` (`$PORT`) - Caddy server hosting the frontend statically and proxying requests to the backend.
+
+- `8080` (`$PORT`) - Caddy server hosting the frontend statically and proxying requests to the backend.
 
 The deployment also runs a local Redis server to store state for each user.
 
 Conceptually it is similar to the `simple-one-port` example except it:
-  * has layer caching for python, reflex, and node dependencies
-  * uses multi-stage build to reduce the size of the final image
+
+- has layer caching for python, reflex, and node dependencies
+- uses multi-stage build to reduce the size of the final image
 
 Using this method may be preferable for deploying in memory constrained
 environments, because it serves a static frontend export, rather than running
@@ -34,4 +36,4 @@ uploaded_files directories as needed.
 This container should be used with an existing load balancer or reverse proxy to
 terminate TLS.
 
-It is also useful for deploying to simple app platforms, such as Render or Heroku.
+It is also useful for deploying to simple app platforms, such as Render or Heroku.

+ 3 - 2
docker-example/simple-one-port/README.md

@@ -1,7 +1,8 @@
 # simple-one-port
 
 This docker deployment runs Reflex in prod mode, exposing a single HTTP port:
-  * `8080` (`$PORT`) - Caddy server hosting the frontend statically and proxying requests to the backend.
+
+- `8080` (`$PORT`) - Caddy server hosting the frontend statically and proxying requests to the backend.
 
 The deployment also runs a local Redis server to store state for each user.
 
@@ -33,4 +34,4 @@ uploaded_files directories as needed.
 This container should be used with an existing load balancer or reverse proxy to
 terminate TLS.
 
-It is also useful for deploying to simple app platforms, such as Render or Heroku.
+It is also useful for deploying to simple app platforms, such as Render or Heroku.

+ 4 - 3
docker-example/simple-two-port/README.md

@@ -1,8 +1,9 @@
 # simple-two-port
 
 This docker deployment runs Reflex in prod mode, exposing two HTTP ports:
-  * `3000` - node NextJS server using optimized production build
-  * `8000` - python gunicorn server hosting the Reflex backend
+
+- `3000` - node NextJS server using optimized production build
+- `8000` - python gunicorn server hosting the Reflex backend
 
 The deployment also runs a local Redis server to store state for each user.
 
@@ -41,4 +42,4 @@ handle @backend_routes {
 }
 
 reverse_proxy localhost:3000
-```
+```

+ 13 - 13
docs/DEBUGGING.md

@@ -12,17 +12,17 @@ app with breakpoints.
 
 ```json
 {
-    "version": "0.2.0",
-    "configurations": [
-        {
-            "name": "Reflex App",
-            "type": "python",
-            "request": "launch",
-            "module": "reflex",
-            "args": "run --env dev",
-            "justMyCode": true,
-            "cwd": "${fileDirname}/.."
-        }
-    ]
+  "version": "0.2.0",
+  "configurations": [
+    {
+      "name": "Reflex App",
+      "type": "python",
+      "request": "launch",
+      "module": "reflex",
+      "args": "run --env dev",
+      "justMyCode": true,
+      "cwd": "${fileDirname}/.."
+    }
+  ]
 }
-```
+```

+ 12 - 19
docs/de/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
@@ -6,10 +5,12 @@
 <hr>
 
 ### **✨ Performante, anpassbare Web-Apps in purem Python. Bereitstellung in Sekunden. ✨**
+
 [![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)
 ![versions](https://img.shields.io/pypi/pyversions/reflex.svg)
 [![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)
 [![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)
+
 </div>
 
 ---
@@ -23,9 +24,10 @@
 Reflex ist eine Bibliothek, mit der man Full-Stack-Web-Applikationen in purem Python erstellen kann.
 
 Wesentliche Merkmale:
-* **Pures Python** - Schreibe dein Front- und Backend in Python, es gibt also keinen Grund, JavaScript zu lernen.
-* **Volle Flexibilität** - Reflex ist einfach zu handhaben, kann aber auch für komplexe Anwendungen skaliert werden.
-* **Sofortige Bereitstellung** - Nach dem Erstellen kannst du deine App mit einem [einzigen Befehl](https://reflex.dev/docs/hosting/deploy-quick-start/) bereitstellen oder auf deinem eigenen Server hosten.
+
+- **Pures Python** - Schreibe dein Front- und Backend in Python, es gibt also keinen Grund, JavaScript zu lernen.
+- **Volle Flexibilität** - Reflex ist einfach zu handhaben, kann aber auch für komplexe Anwendungen skaliert werden.
+- **Sofortige Bereitstellung** - Nach dem Erstellen kannst du deine App mit einem [einzigen Befehl](https://reflex.dev/docs/hosting/deploy-quick-start/) bereitstellen oder auf deinem eigenen Server hosten.
 
 Auf unserer [Architektur-Seite](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) erfahren Sie, wie Reflex unter der Haube funktioniert.
 
@@ -61,7 +63,6 @@ Du solltest deine App unter http://localhost:3000 laufen sehen.
 
 Nun kannst du den Quellcode in `my_app_name/my_app_name.py` ändern. Reflex hat schnelle Aktualisierungen, sodass du deine Änderungen sofort siehst, wenn du deinen Code speicherst.
 
-
 ## 🫧 Beispiel-App
 
 Lass uns ein Beispiel durchgehen: die Erstellung einer Benutzeroberfläche für die Bildgenerierung mit [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node). Zur Vereinfachung rufen wir einfach die [OpenAI-API](https://platform.openai.com/docs/api-reference/authentication) auf, aber du könntest dies auch durch ein lokal ausgeführtes ML-Modell ersetzen.
@@ -76,8 +77,6 @@ Lass uns ein Beispiel durchgehen: die Erstellung einer Benutzeroberfläche für
 
 Hier ist der komplette Code, um dies zu erstellen. Das alles wird in einer Python-Datei gemacht!
 
-
-  
 ```python
 import reflex as rx
 import openai
@@ -117,7 +116,7 @@ def index():
                 width="25em",
             ),
             rx.button(
-                "Generate Image", 
+                "Generate Image",
                 on_click=State.get_image,
                 width="25em",
                 loading=State.processing
@@ -137,17 +136,12 @@ app = rx.App()
 app.add_page(index, title="Reflex:DALL-E")
 ```
 
-
-
-
-
 ## Schauen wir uns das mal genauer an.
 
 <div align="center">
 <img src="docs/images/dalle_colored_code_example.png" alt="Erläuterung der Unterschiede zwischen Backend- und Frontend-Teilen der DALL-E-App." width="900" />
 </div>
 
-
 ### **Reflex-UI**
 
 Fangen wir mit der Benutzeroberfläche an.
@@ -224,11 +218,10 @@ Du kannst eine mehrseitige App erstellen, indem du weitere Seiten hinzufügst.
 
 <div align="center">
 
-📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [Komponentenbibliothek](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [Galerie](https://reflex.dev/docs/gallery) &nbsp; |  &nbsp; 🛸 [Bereitstellung](https://reflex.dev/docs/hosting/deploy-quick-start)  &nbsp;   
+📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Komponentenbibliothek](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Galerie](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [Bereitstellung](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
 
 </div>
 
-
 ## ✅ Status
 
 Reflex wurde im Dezember 2022 unter dem Namen Pynecone gestartet.
@@ -241,14 +234,14 @@ Reflex hat wöchentliche Veröffentlichungen und neue Features! Stelle sicher, d
 
 Wir begrüßen Beiträge jeder Größe! Hier sind einige gute Möglichkeiten, um in der Reflex-Community zu starten.
 
--   **Tritt unserem Discord bei**: Unser [Discord](https://discord.gg/T5WSbC2YtQ) ist der beste Ort, um Hilfe für dein Reflex-Projekt zu bekommen und zu besprechen, wie du beitragen kannst.
--   **GitHub-Diskussionen**: Eine großartige Möglichkeit, über Funktionen zu sprechen, die du hinzugefügt haben möchtest oder Dinge, die verwirrend sind/geklärt werden müssen.
--   **GitHub-Issues**: [Issues](https://github.com/reflex-dev/reflex/issues) sind eine ausgezeichnete Möglichkeit, Bugs zu melden. Außerdem kannst du versuchen, ein bestehendes Problem zu lösen und eine PR einzureichen.
+- **Tritt unserem Discord bei**: Unser [Discord](https://discord.gg/T5WSbC2YtQ) ist der beste Ort, um Hilfe für dein Reflex-Projekt zu bekommen und zu besprechen, wie du beitragen kannst.
+- **GitHub-Diskussionen**: Eine großartige Möglichkeit, über Funktionen zu sprechen, die du hinzugefügt haben möchtest oder Dinge, die verwirrend sind/geklärt werden müssen.
+- **GitHub-Issues**: [Issues](https://github.com/reflex-dev/reflex/issues) sind eine ausgezeichnete Möglichkeit, Bugs zu melden. Außerdem kannst du versuchen, ein bestehendes Problem zu lösen und eine PR einzureichen.
 
 Wir suchen aktiv nach Mitwirkenden, unabhängig von deinem Erfahrungslevel oder deiner Erfahrung. Um beizutragen, sieh dir [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) an.
 
-
 ## Vielen Dank an unsere Mitwirkenden:
+
 <a href="https://github.com/reflex-dev/reflex/graphs/contributors">
   <img src="https://contrib.rocks/image?repo=reflex-dev/reflex" />
 </a>

+ 12 - 12
docs/es/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
@@ -6,11 +5,13 @@
 <hr>
 
 ### **✨ Aplicaciones web personalizables y eficaces en Python puro. Despliega tu aplicación en segundos. ✨**
+
 [![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)
 ![Pruebas](https://github.com/pynecone-io/pynecone/actions/workflows/integration.yml/badge.svg)
 ![Versiones](https://img.shields.io/pypi/pyversions/reflex.svg)
 [![Documentación](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)
 [![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)
+
 </div>
 
 ---
@@ -24,9 +25,10 @@
 Reflex es una biblioteca para construir aplicaciones web full-stack en Python puro.
 
 Características clave:
-* **Python puro** - Escribe el frontend y backend de tu aplicación en Python, sin necesidad de aprender JavaScript.
-* **Flexibilidad total** - Reflex es fácil para empezar, pero también puede escalar a aplicaciones complejas.
-* **Despliegue instantáneo** - Después de construir, despliega tu aplicación con un [solo comando](https://reflex.dev/docs/hosting/deploy-quick-start/) u hospédala en tu propio servidor.
+
+- **Python puro** - Escribe el frontend y backend de tu aplicación en Python, sin necesidad de aprender JavaScript.
+- **Flexibilidad total** - Reflex es fácil para empezar, pero también puede escalar a aplicaciones complejas.
+- **Despliegue instantáneo** - Después de construir, despliega tu aplicación con un [solo comando](https://reflex.dev/docs/hosting/deploy-quick-start/) u hospédala en tu propio servidor.
 
 Consulta nuestra [página de arquitectura](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) para aprender cómo funciona Reflex en detalle.
 
@@ -62,7 +64,6 @@ Debería ver su aplicación ejecutándose en http://localhost:3000.
 
 Ahora puede modificar el código fuente en `my_app_name/my_app_name.py`. Reflex se actualiza rápidamente para que pueda ver los cambios al instante cuando guarde el código.
 
-
 ## 🫧 Ejemplo de una Aplicación
 
 Veamos un ejemplo: crearemos una UI de generación de imágenes en torno a [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node). Para simplificar, solo llamamos a la [API de OpenAI](https://platform.openai.com/docs/api-reference/authentication), pero podrías reemplazar esto con un modelo ML ejecutado localmente.
@@ -102,7 +103,7 @@ class State(rx.State):
         )
         self.image_url = response.data[0].url
         self.processing, self.complete = False, True
-        
+
 
 def index():
     return rx.center(
@@ -114,7 +115,7 @@ def index():
                 width="25em",
             ),
             rx.button(
-                "Generate Image", 
+                "Generate Image",
                 on_click=State.get_image,
                 width="25em",
                 loading=State.processing
@@ -215,11 +216,10 @@ Puedes crear una aplicación multipágina añadiendo más páginas.
 
 <div align="center">
 
-📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [Librería de componentes](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [Galería](https://reflex.dev/docs/gallery) &nbsp; |  &nbsp; 🛸 [Despliegue](https://reflex.dev/docs/hosting/deploy-quick-start)  &nbsp;   
+📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Librería de componentes](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Galería](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [Despliegue](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
 
 </div>
 
-
 ## ✅ Estado
 
 Reflex se lanzó en diciembre de 2022 con el nombre de Pynecone.
@@ -232,9 +232,9 @@ Reflex se lanzó en diciembre de 2022 con el nombre de Pynecone.
 
 ¡Aceptamos contribuciones de cualquier tamaño! A continuación encontrará algunas buenas formas de iniciarse en la comunidad Reflex.
 
--   **Únete a nuestro  Discord**: Nuestro [Discord](https://discord.gg/T5WSbC2YtQ) es el mejor lugar para obtener ayuda en su proyecto Reflex y discutir cómo puedes contribuir.
--   **Discusiones de GitHub**: Una excelente manera de hablar sobre las características que deseas agregar o las cosas que te resultan confusas o necesitan aclaración.
--   **GitHub Issues**: Las incidencias son una forma excelente de informar de errores. Además, puedes intentar resolver un problema existente y enviar un PR.
+- **Únete a nuestro Discord**: Nuestro [Discord](https://discord.gg/T5WSbC2YtQ) es el mejor lugar para obtener ayuda en su proyecto Reflex y discutir cómo puedes contribuir.
+- **Discusiones de GitHub**: Una excelente manera de hablar sobre las características que deseas agregar o las cosas que te resultan confusas o necesitan aclaración.
+- **GitHub Issues**: Las incidencias son una forma excelente de informar de errores. Además, puedes intentar resolver un problema existente y enviar un PR.
 
 Buscamos colaboradores, sin importar su nivel o experiencia. Para contribuir consulta [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
 

+ 0 - 1
docs/in/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex लोगो" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex लोगो" width="300px">

+ 14 - 12
docs/it/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
@@ -6,15 +5,19 @@
 <hr>
 
 ### **✨ App web performanti e personalizzabili in puro Python. Distribuisci in pochi secondi. ✨**
+
 [![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)
 ![versions](https://img.shields.io/pypi/pyversions/reflex.svg)
 [![Documentaiton](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)
 [![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)
+
 </div>
 
 ---
+
 [English](https://github.com/reflex-dev/reflex/blob/main/README.md) | [简体中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_cn/README.md) | [繁體中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_tw/README.md) | [Türkçe](https://github.com/reflex-dev/reflex/blob/main/docs/tr/README.md) | [हिंदी](https://github.com/reflex-dev/reflex/blob/main/docs/in/README.md) | [Português (Brasil)](https://github.com/reflex-dev/reflex/blob/main/docs/pt/pt_br/README.md) |
 [Italiano](https://github.com/reflex-dev/reflex/blob/main/docs/it/README.md) | [한국어](https://github.com/reflex-dev/reflex/blob/main/docs/kr/README.md) | [日本語](https://github.com/reflex-dev/reflex/blob/main/docs/ja/README.md) | [Deutsch](https://github.com/reflex-dev/reflex/blob/main/docs/de/README.md) | [Persian (پارسی)](https://github.com/reflex-dev/reflex/blob/main/docs/pe/README.md)
+
 ---
 
 ## ⚙️ Installazione
@@ -86,7 +89,7 @@ class State(rx.State):
         response = openai.Image.create(prompt=self.prompt, n=1, size="1024x1024")
         self.image_url = response["data"][0]["url"]
         self.processing, self.complete = False, True
-        
+
 def index():
     return rx.center(
         rx.vstack(
@@ -172,7 +175,7 @@ def get_image(self):
 
 Dentro lo stato, definiamo funzioni chiamate gestori di eventi che cambiano le vars dello stato. I gestori di eventi sono il modo in cui possiamo modificare lo stato in Reflex. Possono essere chiamati in risposta alle azioni dell'utente, come fare clic su un pulsante o digitare in una casella di testo. Queste azioni vengono chiamate eventi.
 
-La nostra app DALL·E ha un gestore di eventi, `get_image` con cui ottiene questa immagine dall'API OpenAI. Utilizzando `yield`  nel mezzo di un gestore di eventi farà sì che l'UI venga aggiornata. Altrimenti, l'UI verrà aggiornata alla fine del gestore di eventi.
+La nostra app DALL·E ha un gestore di eventi, `get_image` con cui ottiene questa immagine dall'API OpenAI. Utilizzando `yield` nel mezzo di un gestore di eventi farà sì che l'UI venga aggiornata. Altrimenti, l'UI verrà aggiornata alla fine del gestore di eventi.
 
 ### **Instradamento (Routing)**
 
@@ -194,7 +197,7 @@ Puoi creare un'app multi-pagina aggiungendo altre pagine.
 
 <div align="center">
 
-📑 [Documentazione](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [Libreria Componenti](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [Immagini](https://reflex.dev/docs/gallery) &nbsp; |  &nbsp; 🛸 [Distribuzione](https://reflex.dev/docs/hosting/deploy)  &nbsp;   
+📑 [Documentazione](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Libreria Componenti](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Immagini](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [Distribuzione](https://reflex.dev/docs/hosting/deploy) &nbsp;
 
 </div>
 
@@ -204,10 +207,10 @@ Reflex è stato lanciato nel dicembre 2022 con il nome Pynecone.
 
 Da luglio 2023, siamo nella fase di Beta Pubblica.
 
--   :white_check_mark: **Alfa Pubblica**: Chiunque può installare e utilizzare Reflex. Potrebbero esserci dei problemi, ma stiamo lavorando per risolverli attivamente.
--   :large_orange_diamond: **Beta Pubblica**: Abbastanza stabile per casi d'uso non aziendali.
--   **Beta Hosting Pubblico**: _Opzionalmente_, distribuisci e ospita le tue app su Reflex! 
--   **Pubblico**: Reflex è pronto per la produzione. 
+- :white_check_mark: **Alfa Pubblica**: Chiunque può installare e utilizzare Reflex. Potrebbero esserci dei problemi, ma stiamo lavorando per risolverli attivamente.
+- :large_orange_diamond: **Beta Pubblica**: Abbastanza stabile per casi d'uso non aziendali.
+- **Beta Hosting Pubblico**: _Opzionalmente_, distribuisci e ospita le tue app su Reflex!
+- **Pubblico**: Reflex è pronto per la produzione.
 
 Reflex ha nuove versioni e funzionalità in arrivo ogni settimana! Assicurati di :star: mettere una stella e :eyes: osservare questa repository per rimanere aggiornato.
 
@@ -215,13 +218,12 @@ Reflex ha nuove versioni e funzionalità in arrivo ogni settimana! Assicurati di
 
 Diamo il benvenuto a contributi di qualsiasi dimensione! Di seguito sono alcuni modi per iniziare nella comunità Reflex.
 
--   **Unisciti al nostro Discord**: Il nostro [Discord](https://discord.gg/T5WSbC2YtQ) è posto migliore per ottenere aiuto sul tuo progetto Reflex e per discutere come puoi contribuire.
--   **Discussioni su GitHub**: Un ottimo modo per parlare delle funzionalità che desideri aggiungere o di cose che creano confusione o necessitano chiarimenti.
--   **GitHub Issues**: Sono un ottimo modo per segnalare bug. Inoltre, puoi provare a risolvere un problema esistente e inviare un PR. 
+- **Unisciti al nostro Discord**: Il nostro [Discord](https://discord.gg/T5WSbC2YtQ) è posto migliore per ottenere aiuto sul tuo progetto Reflex e per discutere come puoi contribuire.
+- **Discussioni su GitHub**: Un ottimo modo per parlare delle funzionalità che desideri aggiungere o di cose che creano confusione o necessitano chiarimenti.
+- **GitHub Issues**: Sono un ottimo modo per segnalare bug. Inoltre, puoi provare a risolvere un problema esistente e inviare un PR.
 
 Stiamo attivamente cercando collaboratori, indipendentemente dal tuo livello di abilità o esperienza.
 
-
 ## Licenza
 
 Reflex è open-source e rilasciato sotto la [Licenza Apache 2.0](LICENSE).

+ 0 - 1
docs/ja/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">

+ 16 - 20
docs/kr/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
@@ -6,15 +5,18 @@
 <hr>
 
 ### **✨ 순수 Python으로 고성능 사용자 정의 웹앱을 만들어 보세요. 몇 초만에 배포 가능합니다. ✨**
+
 [![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)
 ![versions](https://img.shields.io/pypi/pyversions/reflex.svg)
 [![Documentaiton](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)
 [![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)
+
 </div>
 
 ---
-[English](https://github.com/reflex-dev/reflex/blob/main/README.md) | [简体中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_cn/README.md) | [繁體中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_tw/README.md) | [Türkçe](https://github.com/reflex-dev/reflex/blob/main/docs/tr/README.md) | [हिंदी](https://github.com/reflex-dev/reflex/blob/main/docs/in/README.md) | [Português (Brasil)](https://github.com/reflex-dev/reflex/blob/main/docs/pt/pt_br/README.md) | [Italiano](https://github.com/reflex-dev/reflex/blob/main/docs/it/README.md) | [한국어](https://github.com/reflex-dev/reflex/blob/main/docs/kr/README.md) | [日本語](https://github.com/reflex-dev/reflex/blob/main/docs/ja/README.md) | [Deutsch](https://github.com/reflex-dev/reflex/blob/main/docs/de/README.md) | [Persian (پارسی)](https://github.com/reflex-dev/reflex/blob/main/docs/pe/README.md)
----
+
+## [English](https://github.com/reflex-dev/reflex/blob/main/README.md) | [简体中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_cn/README.md) | [繁體中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_tw/README.md) | [Türkçe](https://github.com/reflex-dev/reflex/blob/main/docs/tr/README.md) | [हिंदी](https://github.com/reflex-dev/reflex/blob/main/docs/in/README.md) | [Português (Brasil)](https://github.com/reflex-dev/reflex/blob/main/docs/pt/pt_br/README.md) | [Italiano](https://github.com/reflex-dev/reflex/blob/main/docs/it/README.md) | [한국어](https://github.com/reflex-dev/reflex/blob/main/docs/kr/README.md) | [日本語](https://github.com/reflex-dev/reflex/blob/main/docs/ja/README.md) | [Deutsch](https://github.com/reflex-dev/reflex/blob/main/docs/de/README.md) | [Persian (پارسی)](https://github.com/reflex-dev/reflex/blob/main/docs/pe/README.md)
+
 ## ⚙️ 설치
 
 터미널을 열고 실행하세요. (Python 3.10+ 필요):
@@ -47,7 +49,6 @@ http://localhost:3000 에서 앱이 실행 됩니다.
 
 이제 `my_app_name/my_app_name.py`에서 소스코드를 수정할 수 있습니다. Reflex는 빠른 새로고침을 지원하므로 코드를 저장할 때마다 즉시 변경 사항을 볼 수 있습니다.
 
-
 ## 🫧 예시 앱
 
 예시를 살펴보겠습니다: DALL·E를 중심으로 이미지 생성 UI를 만들어 보겠습니다. 간단하게 하기 위해 OpenAI API를 호출했지만, 이를 로컬에서 실행되는 ML 모델로 대체할 수 있습니다.
@@ -101,7 +102,7 @@ def index():
                 width="25em",
             ),
             rx.button(
-                "Generate Image", 
+                "Generate Image",
                 on_click=State.get_image,
                 width="25em",
                 loading=State.processing
@@ -136,11 +137,10 @@ def index():
 
 `index` 함수는 앱의 프론트엔드를 정의합니다.
 
-`center`, `vstack`, `input`, `button`과 같은 다양한 컴포넌트를 사용하여 프론트엔드를 구축합니다. 
-컴포넌트들은 복잡한 레이아웃을 만들기 위해 서로 중첩될 수 있습니다. 
+`center`, `vstack`, `input`, `button`과 같은 다양한 컴포넌트를 사용하여 프론트엔드를 구축합니다.
+컴포넌트들은 복잡한 레이아웃을 만들기 위해 서로 중첩될 수 있습니다.
 그리고 키워드 인자를 사용하여 CSS의 모든 기능을 사용하여 스타일을 지정할 수 있습니다.
 
-
 Reflex는 시작하기 위한 [60개 이상의 기본 컴포넌트](https://reflex.dev/docs/library)를 제공하고 있습니다. 더 많은 컴포넌트를 추가하고 있으며, [자신만의 컴포넌트를 생성하는 것](https://reflex.dev/docs/wrapping-react/overview/)도 쉽습니다.
 
 ### **State**
@@ -201,24 +201,20 @@ app.add_page(index, title="DALL-E")
 
 <div align="center">
 
-📑 [문서](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [블로그](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [컴포넌트 라이브러리](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [갤러리](https://reflex.dev/docs/gallery) &nbsp; |  &nbsp; 🛸 [배포](https://reflex.dev/docs/hosting/deploy)  &nbsp;   
+📑 [문서](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [블로그](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [컴포넌트 라이브러리](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [갤러리](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [배포](https://reflex.dev/docs/hosting/deploy) &nbsp;
 
 </div>
 
-
-
-
-
 ## ✅ 상태
 
 Reflex는 2022년 12월 Pynecone이라는 이름으로 출시되었습니다.
 
 2023년 7월 현재, 우리는 **Public Beta** 상태에 있습니다.
 
--   :white_check_mark: **Public Alpha**: 누구나 Reflex를 설치하고 사용할 수 있습니다. 문제가 발생할 수도 있지만 적극적으로 수정합니다.
--   :large_orange_diamond: **Public Beta**: 비상업적 용도로 충분히 안정적입니다.
--   **Public Hosting Beta**: _선택적으로_, Reflex에서 앱을 배포하고 호스팅할 수 있습니다!
--   **Public** : Reflex는 프로덕션 준비를 마쳤습니다.
+- :white_check_mark: **Public Alpha**: 누구나 Reflex를 설치하고 사용할 수 있습니다. 문제가 발생할 수도 있지만 적극적으로 수정합니다.
+- :large_orange_diamond: **Public Beta**: 비상업적 용도로 충분히 안정적입니다.
+- **Public Hosting Beta**: _선택적으로_, Reflex에서 앱을 배포하고 호스팅할 수 있습니다!
+- **Public** : Reflex는 프로덕션 준비를 마쳤습니다.
 
 Reflex는 매주 새로운 릴리즈와 기능을 제공합니다! 최신 정보를 확인하려면 :star: Star와 :eyes: Watch를 눌러 이 저장소를 확인하세요.
 
@@ -226,9 +222,9 @@ Reflex는 매주 새로운 릴리즈와 기능을 제공합니다! 최신 정보
 
 우리는 모든 기여를 환영합니다! 아래는 Reflex 커뮤니티에 참여하는 좋은 방법입니다.
 
--   **Discord 참여**: 우리의 [Discord](https://discord.gg/T5WSbC2YtQ)는 Reflex 프로젝트에 대한 도움을 받고 기여하는 방법을 논의하는 최고의 장소입니다.
--   **GitHub Discussions**: 추가하고 싶은 기능이나 혼란스럽거나 해결이 필요한 것들에 대해 이야기하는 좋은 방법입니다.
--   **GitHub Issues**: 이것은 버그를 보고하는 훌륭한 방법입니다. 또한, 기존의 이슈를 해결하고 PR을 제출할 수 있습니다.
+- **Discord 참여**: 우리의 [Discord](https://discord.gg/T5WSbC2YtQ)는 Reflex 프로젝트에 대한 도움을 받고 기여하는 방법을 논의하는 최고의 장소입니다.
+- **GitHub Discussions**: 추가하고 싶은 기능이나 혼란스럽거나 해결이 필요한 것들에 대해 이야기하는 좋은 방법입니다.
+- **GitHub Issues**: 이것은 버그를 보고하는 훌륭한 방법입니다. 또한, 기존의 이슈를 해결하고 PR을 제출할 수 있습니다.
 
 우리는 능력이나 경험에 상관없이 적극적으로 기여자를 찾고 있습니다.
 

+ 16 - 23
docs/pe/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
@@ -6,10 +5,12 @@
 <hr>
 
 ### **✨ برنامه های تحت وب قابل تنظیم، کارآمد تماما پایتونی که در چند ثانیه مستقر(دپلوی) می‎شود. ✨**
+
 [![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)
 ![versions](https://img.shields.io/pypi/pyversions/reflex.svg)
 [![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)
 [![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)
+
 </div>
 
 ---
@@ -23,9 +24,10 @@
 رفلکس(Reflex) یک کتابخانه برای ساخت برنامه های وب فول استک تماما پایتونی است.
 
 ویژگی های کلیدی:
-* **تماما پایتونی** - فرانت اند و بک اند برنامه خود را همه در پایتون بنویسید، بدون نیاز به یادگیری جاوا اسکریپت.
-* **انعطاف پذیری کامل** - شروع به کار با Reflex آسان است، اما می تواند به برنامه های پیچیده نیز تبدیل شود.
-* **دپلوی فوری** - پس از ساخت، برنامه خود را با [یک دستور](https://reflex.dev/docs/hosting/deploy-quick-start/) دپلوی کنید یا آن را روی سرور خود میزبانی کنید.
+
+- **تماما پایتونی** - فرانت اند و بک اند برنامه خود را همه در پایتون بنویسید، بدون نیاز به یادگیری جاوا اسکریپت.
+- **انعطاف پذیری کامل** - شروع به کار با Reflex آسان است، اما می تواند به برنامه های پیچیده نیز تبدیل شود.
+- **دپلوی فوری** - پس از ساخت، برنامه خود را با [یک دستور](https://reflex.dev/docs/hosting/deploy-quick-start/) دپلوی کنید یا آن را روی سرور خود میزبانی کنید.
 
 برای آشنایی با نحوه عملکرد Reflex [صفحه معماری](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) را ببینید.
 
@@ -61,7 +63,6 @@ reflex run
 
 اکنون می‌توانید کد منبع را در «my_app_name/my_app_name.py» تغییر دهید. Reflex دارای تازه‌سازی‌های سریعی است، بنابراین می‌توانید تغییرات خود را بلافاصله پس از ذخیره کد خود مشاهده کنید.
 
-
 ## 🫧 Example App - برنامه نمونه
 
 بیایید یک مثال بزنیم: ایجاد یک رابط کاربری برای تولید تصویر [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node). برای سادگی، ما فراخوانی میکنیم [OpenAI API](https://platform.openai.com/docs/api-reference/authentication), اما می توانید آن را با یک مدل ML که به صورت محلی اجرا می شود جایگزین کنید.
@@ -76,8 +77,6 @@ reflex run
 
 در اینجا کد کامل برای ایجاد این پروژه آمده است. همه اینها در یک فایل پایتون انجام می شود!
 
-
-  
 ```python
 import reflex as rx
 import openai
@@ -117,7 +116,7 @@ def index():
                 width="25em",
             ),
             rx.button(
-                "Generate Image", 
+                "Generate Image",
                 on_click=State.get_image,
                 width="25em",
                 loading=State.processing
@@ -137,18 +136,13 @@ app = rx.App()
 app.add_page(index, title="Reflex:DALL-E")
 ```
 
-
-
-
-
 ## بیاید سادش کنیم
 
 <div align="center">
 <img src="docs/images/dalle_colored_code_example.png" alt="Explaining the differences between backend and frontend parts of the DALL-E app." width="900" />
 </div>
 
-
-### **Reflex UI - رابط کاربری رفلکس** 
+### **Reflex UI - رابط کاربری رفلکس**
 
 بیایید با رابط کاربری شروع کنیم.
 
@@ -164,7 +158,7 @@ def index():
 ما از اجزای مختلفی مثل `center`, `vstack`, `input` و `button` استفاده میکنیم تا فرانت اند را بسازیم. اجزاء را می توان درون یکدیگر قرار داد
 برای ایجاد طرح بندی های پیچیده می توانید از args کلمات کلیدی برای استایل دادن به آنها از CSS استفاده کنید.
 
-رفلکس دارای [بیش از 60  جزء](https://reflex.dev/docs/library) برای کمک به شما برای شروع. ما به طور فعال اجزای بیشتری را اضافه می کنیم, و این خیلی آسان است که [اجزا خود را بسازید](https://reflex.dev/docs/wrapping-react/overview/).
+رفلکس دارای [بیش از 60 جزء](https://reflex.dev/docs/library) برای کمک به شما برای شروع. ما به طور فعال اجزای بیشتری را اضافه می کنیم, و این خیلی آسان است که [اجزا خود را بسازید](https://reflex.dev/docs/wrapping-react/overview/).
 
 ### **State - حالت**
 
@@ -225,31 +219,30 @@ app.add_page(index, title="DALL-E")
 
 <div align="center">
 
-📑 [اسناد](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [وبلاگ](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [کتابخانه جزء](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [گالری](https://reflex.dev/docs/gallery) &nbsp; |  &nbsp; 🛸 [استقرار](https://reflex.dev/docs/hosting/deploy-quick-start)  &nbsp;   
+📑 [اسناد](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [وبلاگ](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [کتابخانه جزء](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [گالری](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [استقرار](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
 
 </div>
 
-
 ## ✅ Status - وضعیت
 
 رفلکس(reflex) در دسامبر 2022 با نام Pynecone راه اندازی شد.
 
 از فوریه 2024، سرویس میزبانی ما در آلفا است! در این مدت هر کسی می‌تواند برنامه‌های خود را به صورت رایگان اجرا کند. [نقشه راه](https://github.com/reflex-dev/reflex/issues/2727) را ببینید تا متوجه شوید چه برنامه‌ریزی شده است.
 
-رفلکس(reflex) هر هفته نسخه ها و ویژگی های جدیدی دارد! مطمئن شوید که :star: ستاره و  :eyes: این مخزن را تماشا کنید تا به روز بمانید.
+رفلکس(reflex) هر هفته نسخه ها و ویژگی های جدیدی دارد! مطمئن شوید که :star: ستاره و :eyes: این مخزن را تماشا کنید تا به روز بمانید.
 
 ## Contributing - مشارکت کردن
 
 ما از مشارکت در هر اندازه استقبال می کنیم! در زیر چند راه خوب برای شروع در انجمن رفلکس آورده شده است.
 
--   **به Discord ما بپیوندید**: [Discord](https://discord.gg/T5WSbC2YtQ) ما بهترین مکان برای دریافت کمک در مورد پروژه Reflex و بحث در مورد اینکه چگونه می توانید کمک کنید است.
--   **بحث های GitHub**: راهی عالی برای صحبت در مورد ویژگی هایی که می خواهید اضافه کنید یا چیزهایی که گیج کننده هستند/نیاز به توضیح دارند.
--   **قسمت مشکلات GitHub**: [قسمت مشکلات](https://github.com/reflex-dev/reflex/issues) یک راه عالی برای گزارش اشکال هستند. علاوه بر این، می توانید یک مشکل موجود را حل کنید و یک PR(pull request) ارسال کنید.
-
-ما فعالانه به دنبال مشارکت کنندگان هستیم، فارغ از سطح مهارت یا تجربه شما. برای مشارکت  [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) را بررسی کنید.
+- **به Discord ما بپیوندید**: [Discord](https://discord.gg/T5WSbC2YtQ) ما بهترین مکان برای دریافت کمک در مورد پروژه Reflex و بحث در مورد اینکه چگونه می توانید کمک کنید است.
+- **بحث های GitHub**: راهی عالی برای صحبت در مورد ویژگی هایی که می خواهید اضافه کنید یا چیزهایی که گیج کننده هستند/نیاز به توضیح دارند.
+- **قسمت مشکلات GitHub**: [قسمت مشکلات](https://github.com/reflex-dev/reflex/issues) یک راه عالی برای گزارش اشکال هستند. علاوه بر این، می توانید یک مشکل موجود را حل کنید و یک PR(pull request) ارسال کنید.
 
+ما فعالانه به دنبال مشارکت کنندگان هستیم، فارغ از سطح مهارت یا تجربه شما. برای مشارکت [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) را بررسی کنید.
 
 ## All Thanks To Our Contributors - با تشکر از همکاران ما:
+
 <a href="https://github.com/reflex-dev/reflex/graphs/contributors">
   <img src="https://contrib.rocks/image?repo=reflex-dev/reflex" />
 </a>

+ 15 - 18
docs/pt/pt_br/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
@@ -6,16 +5,19 @@
 <hr>
 
 ### **✨ Web apps customizáveis, performáticos, em Python puro. Faça deploy em segundos. ✨**
+
 [![Versão PyPI](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)
 ![testes](https://github.com/pynecone-io/pynecone/actions/workflows/integration.yml/badge.svg)
 ![versões](https://img.shields.io/pypi/pyversions/reflex.svg)
 [![Documentação](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)
 [![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)
+
 </div>
 
 ---
-[English](https://github.com/reflex-dev/reflex/blob/main/README.md) | [简体中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_cn/README.md) | [繁體中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_tw/README.md) | [Türkçe](https://github.com/reflex-dev/reflex/blob/main/docs/tr/README.md) | [हिंदी](https://github.com/reflex-dev/reflex/blob/main/docs/in/README.md) | [Português (Brasil)](https://github.com/reflex-dev/reflex/blob/main/docs/pt/pt_br/README.md) | [한국어](https://github.com/reflex-dev/reflex/blob/main/docs/kr/README.md) | [日本語](https://github.com/reflex-dev/reflex/blob/main/docs/ja/README.md) | [Deutsch](https://github.com/reflex-dev/reflex/blob/main/docs/de/README.md) | [Persian (پارسی)](https://github.com/reflex-dev/reflex/blob/main/docs/pe/README.md)
----
+
+## [English](https://github.com/reflex-dev/reflex/blob/main/README.md) | [简体中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_cn/README.md) | [繁體中文](https://github.com/reflex-dev/reflex/blob/main/docs/zh/zh_tw/README.md) | [Türkçe](https://github.com/reflex-dev/reflex/blob/main/docs/tr/README.md) | [हिंदी](https://github.com/reflex-dev/reflex/blob/main/docs/in/README.md) | [Português (Brasil)](https://github.com/reflex-dev/reflex/blob/main/docs/pt/pt_br/README.md) | [한국어](https://github.com/reflex-dev/reflex/blob/main/docs/kr/README.md) | [日本語](https://github.com/reflex-dev/reflex/blob/main/docs/ja/README.md) | [Deutsch](https://github.com/reflex-dev/reflex/blob/main/docs/de/README.md) | [Persian (پارسی)](https://github.com/reflex-dev/reflex/blob/main/docs/pe/README.md)
+
 ## ⚙️ Instalação
 
 Abra um terminal e execute (Requer Python 3.10+):
@@ -48,7 +50,6 @@ Você deve conseguir verificar seu app sendo executado em http://localhost:3000.
 
 Agora, você pode modificar o código fonte em `nome_do_meu_app/nome_do_meu_app.py`. O Reflex apresenta recarregamento rápido para que você possa ver suas mudanças instantâneamente quando você salva o seu código.
 
-
 ## 🫧 Exemplo de App
 
 Veja o seguinte exemplo: criar uma interface de criação de imagens por meio do DALL-E. Para fins de simplicidade, vamos apenas chamar a API da OpenAI, mas você pode substituir esta solução por qualquer modelo de aprendizado de máquina que preferir, executando localmente.
@@ -86,7 +87,7 @@ class State(rx.State):
         response = openai.Image.create(prompt=self.prompt, n=1, size="1024x1024")
         self.image_url = response["data"][0]["url"]
         self.processing, self.complete = False, True
-        
+
 
 def index():
     return rx.center(
@@ -138,7 +139,7 @@ Esta função `index` define o frontend do app.
 Usamos diferentes componentes, como `center`, `vstack`, `input` e `button`, para construir o frontend. Componentes podem ser aninhados um no do outro
 para criar layouts mais complexos. E você pode usar argumentos de chave-valor para estilizá-los com todo o poder do CSS.
 
-O Reflex vem com [60+ componentes nativos](https://reflex.dev/docs/library) para te ajudar. Estamos adicionando ativamente mais componentes, mas também é fácil [criar seus próprios componentes](https://reflex.dev/docs/wrapping-react/overview/). 
+O Reflex vem com [60+ componentes nativos](https://reflex.dev/docs/library) para te ajudar. Estamos adicionando ativamente mais componentes, mas também é fácil [criar seus próprios componentes](https://reflex.dev/docs/wrapping-react/overview/).
 
 ### **Estado**
 
@@ -196,24 +197,20 @@ Você pode criar mais páginas e adicioná-las ao seu app.
 
 <div align="center">
 
-📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [Biblioteca de Componentes](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [Galeria](https://reflex.dev/docs/gallery) &nbsp; |  &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy)  &nbsp;   
+📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Biblioteca de Componentes](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Galeria](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy) &nbsp;
 
 </div>
 
-
-
-
-
 ## ✅ Status
 
 O Reflex foi lançado em Dezembro de 2022 com o nome Pynecone.
 
 Em Julho de 2023, estamos no estágio de **Beta Público**.
 
--   :white_check_mark: **Alpha Público**: Qualquer um pode instalar e usar o Reflex. Podem existir alguns problemas, mas estamos trabalhando ativamente para resolvê-los.
--   :large_orange_diamond: **Beta Público**: Estável o suficiente para utilizar em projetos pessoais, com menor criticidade.
--   **Hospedagem Pública Beta**: _Opcionalmente_, implante e hospede os seus apps no Reflex!
--   **Público**: O Reflex está pronto para produção.
+- :white_check_mark: **Alpha Público**: Qualquer um pode instalar e usar o Reflex. Podem existir alguns problemas, mas estamos trabalhando ativamente para resolvê-los.
+- :large_orange_diamond: **Beta Público**: Estável o suficiente para utilizar em projetos pessoais, com menor criticidade.
+- **Hospedagem Pública Beta**: _Opcionalmente_, implante e hospede os seus apps no Reflex!
+- **Público**: O Reflex está pronto para produção.
 
 O Reflex agora possui novas versões e funcionalidades sendo lançadas toda semana! Lembre-se de marcar o repositório com uma :star: estrela e :eyes: acompanhe para ficar atualizado sobre o projeto.
 
@@ -221,9 +218,9 @@ O Reflex agora possui novas versões e funcionalidades sendo lançadas toda sema
 
 Nós somos abertos a contribuições de qualquer tamanho! Abaixo, seguem algumas boas formas de começar a contribuir para a comunidade do Reflex.
 
--   **Entre no nosso Discord**: Nosso [Discord](https://discord.gg/T5WSbC2YtQ) é o melhor lugar para conseguir ajuda no seu projeto Reflex e para discutir como você pode contribuir.
--   **Discussões no GitHub**: Uma boa forma de conversar sobre funcionalidades que você gostaria de ver ou coisas que ainda estão confusas/exigem ajuda.
--   **Issues no GitHub**: Excelente forma de reportar bugs. Além disso, você pode tentar resolver alguma issue existente e enviar um Pull Request.
+- **Entre no nosso Discord**: Nosso [Discord](https://discord.gg/T5WSbC2YtQ) é o melhor lugar para conseguir ajuda no seu projeto Reflex e para discutir como você pode contribuir.
+- **Discussões no GitHub**: Uma boa forma de conversar sobre funcionalidades que você gostaria de ver ou coisas que ainda estão confusas/exigem ajuda.
+- **Issues no GitHub**: Excelente forma de reportar bugs. Além disso, você pode tentar resolver alguma issue existente e enviar um Pull Request.
 
 Estamos ativamente buscando novos contribuidores, não importa o seu nível de habilidade ou experiência.
 

+ 3 - 7
docs/tr/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
@@ -11,6 +10,7 @@
 ![versions](https://img.shields.io/pypi/pyversions/reflex.svg)
 [![Documentaiton](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)
 [![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)
+
 </div>
 
 ---
@@ -88,7 +88,7 @@ class State(rx.State):
         response = openai.Image.create(prompt=self.prompt, n=1, size="1024x1024")
         self.image_url = response["data"][0]["url"]
         self.processing, self.complete = False, True
-        
+
 
 def index():
     return rx.center(
@@ -197,14 +197,10 @@ Daha fazla sayfa ekleyerek çok sayfalı bir uygulama oluşturabilirsiniz.
 
 <div align="center">
 
-📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; |  &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy)  &nbsp;   
+📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy) &nbsp;
 
 </div>
 
-
-
-
-
 ## ✅ Durum
 
 Reflex, Aralık 2022'de Pynecone adıyla piyasaya sürüldü.

+ 15 - 23
docs/vi/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
@@ -6,10 +5,12 @@
 <hr>
 
 ### **✨ Ứng dụng web hiệu suất cao, tùy chỉnh bằng Python thuần. Deploy trong vài giây. ✨**
+
 [![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)
 ![versions](https://img.shields.io/pypi/pyversions/reflex.svg)
 [![Documentation](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)
 [![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)
+
 </div>
 
 ---
@@ -23,9 +24,10 @@
 Reflex là một thư viện để xây dựng ứng dụng web toàn bộ bằng Python thuần.
 
 Các tính năng chính:
-* **Python thuần tuý** - Viết toàn bộ ứng dụng cả backend và frontend hoàn toàn bằng Python, không cần học JavaScript.
-* **Full Flexibility** - Reflex dễ dàng để bắt đầu, nhưng cũng có thể mở rộng lên các ứng dụng phức tạp.
-* **Deploy Instantly** - Sau khi xây dựng ứng dụng, bạn có thể triển khai bằng [một dòng lệnh](https://reflex.dev/docs/hosting/deploy-quick-start/) hoặc triển khai trên server của riêng bạn.
+
+- **Python thuần tuý** - Viết toàn bộ ứng dụng cả backend và frontend hoàn toàn bằng Python, không cần học JavaScript.
+- **Full Flexibility** - Reflex dễ dàng để bắt đầu, nhưng cũng có thể mở rộng lên các ứng dụng phức tạp.
+- **Deploy Instantly** - Sau khi xây dựng ứng dụng, bạn có thể triển khai bằng [một dòng lệnh](https://reflex.dev/docs/hosting/deploy-quick-start/) hoặc triển khai trên server của riêng bạn.
 
 Đọc [bài viết về kiến trúc hệ thống](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture) để hiểu rõ các hoạt động của Reflex.
 
@@ -49,7 +51,7 @@ cd my_app_name
 reflex init
 ```
 
-Lệnh này tạo ra một ứng dụng mẫu trong một thư mục mới. 
+Lệnh này tạo ra một ứng dụng mẫu trong một thư mục mới.
 
 Bạn có thể chạy ứng dụng ở chế độ phát triển.
 
@@ -61,10 +63,9 @@ Bạn có thể xem ứng dụng của bạn ở địa chỉ http://localhost:3
 
 Bạn có thể thay đổi mã nguồn ở `my_app_name/my_app_name.py`. Reflex nhanh chóng làm mới và bạn có thể thấy thay đổi trên ứng dụng của bạn ngay lập tức khi bạn lưu file.
 
-
 ## 🫧 Ứng dụng ví dụ
 
-Bắt đầu với ví dụ: tạo một ứng dụng tạo ảnh bằng [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node). Để cho đơn giản, chúng  ta sẽ sử dụng [OpenAI API](https://platform.openai.com/docs/api-reference/authentication), nhưng bạn có thể sử dụng model của chính bạn được triển khai trên local.
+Bắt đầu với ví dụ: tạo một ứng dụng tạo ảnh bằng [DALL·E](https://platform.openai.com/docs/guides/images/image-generation?context=node). Để cho đơn giản, chúng ta sẽ sử dụng [OpenAI API](https://platform.openai.com/docs/api-reference/authentication), nhưng bạn có thể sử dụng model của chính bạn được triển khai trên local.
 
 &nbsp;
 
@@ -76,8 +77,6 @@ Bắt đầu với ví dụ: tạo một ứng dụng tạo ảnh bằng [DALL·
 
 Đây là toàn bộ đoạn mã để xây dựng ứng dụng trên. Nó được viết hoàn toàn trong một file Python!
 
-
-  
 ```python
 import reflex as rx
 import openai
@@ -117,7 +116,7 @@ def index():
                 width="25em",
             ),
             rx.button(
-                "Generate Image", 
+                "Generate Image",
                 on_click=State.get_image,
                 width="25em",
                 loading=State.processing
@@ -137,17 +136,12 @@ app = rx.App()
 app.add_page(index, title="Reflex:DALL-E")
 ```
 
-
-
-
-
 ## Hãy phân tích chi tiết.
 
 <div align="center">
 <img src="../images/dalle_colored_code_example.png" alt="Explaining the differences between backend and frontend parts of the DALL-E app." width="900" />
 </div>
 
-
 ### **Reflex UI**
 
 Bắt đầu với giao diện chính.
@@ -218,7 +212,6 @@ app = rx.App()
 
 Chúng ta thêm một trang ở đầu ứng dụng bằng index component. Chúng ta cũng thêm tiêu đề của ứng dụng để hiển thị lên trình duyệt.
 
-
 ```python
 app.add_page(index, title="DALL-E")
 ```
@@ -229,11 +222,10 @@ Bạn có thể tạo một ứng dụng nhiều trang bằng cách thêm trang.
 
 <div align="center">
 
-📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; |  &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start)  &nbsp;   
+📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
 
 </div>
 
-
 ## ✅ Status
 
 Reflex phát hành vào tháng 12/2022 với tên là Pynecone.
@@ -246,15 +238,15 @@ Reflex ra phiên bản mới với các tính năng mới hàng tuần! Hãy :st
 
 Chúng tôi chào đón mọi đóng góp dù lớn hay nhỏ. Dưới đây là các cách để bắt đầu với cộng đồng Reflex.
 
--   **Discord**: [Discord](https://discord.gg/T5WSbC2YtQ) của chúng tôi là nơi tốt nhất để nhờ sự giúp đỡ và thảo luận các bạn có thể đóng góp.
--   **GitHub Discussions**: Là cách tốt nhất để thảo luận về các tính năng mà bạn có thể đóng góp hoặc những điều bạn chưa rõ.
--   **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues) là nơi tốt nhất để thông báo. Ngoài ra bạn có thể sửa chữa các vấn đề bằng cách tạo PR.
+- **Discord**: [Discord](https://discord.gg/T5WSbC2YtQ) của chúng tôi là nơi tốt nhất để nhờ sự giúp đỡ và thảo luận các bạn có thể đóng góp.
+- **GitHub Discussions**: Là cách tốt nhất để thảo luận về các tính năng mà bạn có thể đóng góp hoặc những điều bạn chưa rõ.
+- **GitHub Issues**: [Issues](https://github.com/reflex-dev/reflex/issues) là nơi tốt nhất để thông báo. Ngoài ra bạn có thể sửa chữa các vấn đề bằng cách tạo PR.
 
-Chúng tôi luôn sẵn sàng tìm kiếm các contributor, bất kể kinh nghiệm. Để tham gia đóng góp, xin mời xem 
+Chúng tôi luôn sẵn sàng tìm kiếm các contributor, bất kể kinh nghiệm. Để tham gia đóng góp, xin mời xem
 [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
 
-
 ## Xin cảm ơn các Contributors:
+
 <a href="https://github.com/reflex-dev/reflex/graphs/contributors">
   <img src="https://contrib.rocks/image?repo=reflex-dev/reflex" />
 </a>

+ 13 - 20
docs/zh/zh_cn/README.md

@@ -1,4 +1,3 @@
-
 <div align="center">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="https://raw.githubusercontent.com/reflex-dev/reflex/main/docs/images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
@@ -6,10 +5,12 @@
 <hr>
 
 ### **✨ 使用 Python 创建高效且可自定义的网页应用程序,几秒钟内即可部署.✨**
+
 [![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)
 ![versions](https://img.shields.io/pypi/pyversions/reflex.svg)
 [![Documentaiton](https://img.shields.io/badge/Documentation%20-Introduction%20-%20%23007ec6)](https://reflex.dev/docs/getting-started/introduction)
 [![Discord](https://img.shields.io/discord/1029853095527727165?color=%237289da&label=Discord)](https://discord.gg/T5WSbC2YtQ)
+
 </div>
 
 ---
@@ -23,9 +24,10 @@
 Reflex 是一个使用纯Python构建全栈web应用的库。
 
 关键特性:
-* **纯Python** - 前端、后端开发全都使用Python,不需要学习Javascript。
-* **完整的灵活性** - Reflex很容易上手, 并且也可以扩展到复杂的应用程序。
-* **立即部署** - 构建后,使用[单个命令](https://reflex.dev/docs/hosting/deploy-quick-start/)就能部署应用程序;或者也可以将其托管在您自己的服务器上。
+
+- **纯Python** - 前端、后端开发全都使用Python,不需要学习Javascript。
+- **完整的灵活性** - Reflex很容易上手, 并且也可以扩展到复杂的应用程序。
+- **立即部署** - 构建后,使用[单个命令](https://reflex.dev/docs/hosting/deploy-quick-start/)就能部署应用程序;或者也可以将其托管在您自己的服务器上。
 
 请参阅我们的[架构页](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture)了解Reflex如何工作。
 
@@ -75,9 +77,6 @@ reflex run
 
 这是这个范例的完整代码,只需要一个 Python 文件就可以完成!
 
-
-
-
 ```python
 import reflex as rx
 import openai
@@ -87,7 +86,7 @@ openai_client = openai.OpenAI()
 
 class State(rx.State):
     """The app state."""
-    
+
     prompt = ""
     image_url = ""
     processing = False
@@ -117,7 +116,7 @@ def index():
                 width="25em",
             ),
             rx.button(
-                "Generate Image", 
+                "Generate Image",
                 on_click=State.get_image,
                 width="25em",
                 loading=State.processing
@@ -137,17 +136,12 @@ app = rx.App()
 app.add_page(index, title="Reflex:DALL-E")
 ```
 
-
-
-
-
 ## 让我们分解以上步骤.
 
 <div align="center">
 <img src="../../images/dalle_colored_code_example.png" alt="解释 DALL-E app 的前端和后端部分的区别。" width="900" />
 </div>
 
-
 ### **Reflex UI**
 
 让我们从UI开始.
@@ -225,11 +219,10 @@ app.add_page(index, title="DALL-E")
 
 <div align="center">
 
-📑 [文档](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [日志](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [组件库](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [展览](https://reflex.dev/docs/gallery) &nbsp; |  &nbsp; 🛸 [部署](https://reflex.dev/docs/hosting/deploy)  &nbsp;   
+📑 [文档](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [日志](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [组件库](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [展览](https://reflex.dev/docs/gallery) &nbsp; | &nbsp; 🛸 [部署](https://reflex.dev/docs/hosting/deploy) &nbsp;
 
 </div>
 
-
 ## ✅ Reflex 的状态
 
 Reflex 于 2022 年 12 月以Pynecone的名称推出.
@@ -242,14 +235,14 @@ Reflex 每周都有新功能和发布新版本! 确保您按下 :star: 收藏和
 
 我们欢迎任何大小的贡献,以下是几个好的方法来加入 Reflex 社群.
 
--   **加入我们的 Discord**: 我们的 [Discord](https://discord.gg/T5WSbC2YtQ) 是帮助您加入 Reflex 项目和讨论或贡献最棒的地方.
--   **GitHub Discussions**: 一个来讨论您想要添加的功能或是需要澄清的事情的好地方.
--   **GitHub Issues**: [报告错误](https://github.com/reflex-dev/reflex/issues)的绝佳地方,另外您可以试着解决一些 issue 和送出 PR.
+- **加入我们的 Discord**: 我们的 [Discord](https://discord.gg/T5WSbC2YtQ) 是帮助您加入 Reflex 项目和讨论或贡献最棒的地方.
+- **GitHub Discussions**: 一个来讨论您想要添加的功能或是需要澄清的事情的好地方.
+- **GitHub Issues**: [报告错误](https://github.com/reflex-dev/reflex/issues)的绝佳地方,另外您可以试着解决一些 issue 和送出 PR.
 
 我们正在积极寻找贡献者,无关您的技能或经验水平.
 
-
 ## 感谢我们所有的贡献者:
+
 <a href="https://github.com/reflex-dev/reflex/graphs/contributors">
   <img src="https://contrib.rocks/image?repo=reflex-dev/reflex" />
 </a>

+ 13 - 23
docs/zh/zh_tw/README.md

@@ -1,11 +1,10 @@
-
 <div align="center">
 <img src="../../images/reflex_dark.svg#gh-light-mode-only" alt="Reflex Logo" width="300px">
 <img src="../../images/reflex_light.svg#gh-dark-mode-only" alt="Reflex Logo" width="300px">
 
 <hr>
 
-**✨ 使用 Python 建立高效且可自訂的網頁應用程式,幾秒鐘內即可部署。✨**  
+**✨ 使用 Python 建立高效且可自訂的網頁應用程式,幾秒鐘內即可部署。✨**
 
 [![PyPI version](https://badge.fury.io/py/reflex.svg)](https://badge.fury.io/py/reflex)
 ![versions](https://img.shields.io/pypi/pyversions/reflex.svg)
@@ -26,10 +25,10 @@ Reflex 是一個可以用純 Python 構建全端網頁應用程式的函式庫
 
 主要特色:
 
-* **純 Python** - 您可以用 Python 撰寫應用程式的前端和後端,無需學習 Javascript。
-* **完全靈活性** - Reflex 易於上手,但也可以擴展到複雜的應用程式。
-* **立即部署** - 構建後,只需使用[單一指令](https://reflex.dev/docs/hosting/deploy-quick-start/)即可部署您的應用程式,或在您自己的伺服器上託管。
-請參閱我們的[架構頁面](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture)了解 Reflex 如何在底層運作。
+- **純 Python** - 您可以用 Python 撰寫應用程式的前端和後端,無需學習 Javascript。
+- **完全靈活性** - Reflex 易於上手,但也可以擴展到複雜的應用程式。
+- **立即部署** - 構建後,只需使用[單一指令](https://reflex.dev/docs/hosting/deploy-quick-start/)即可部署您的應用程式,或在您自己的伺服器上託管。
+  請參閱我們的[架構頁面](https://reflex.dev/blog/2024-03-21-reflex-architecture/#the-reflex-architecture)了解 Reflex 如何在底層運作。
 
 ## ⚙️ 安裝
 
@@ -103,7 +102,7 @@ class State(rx.State):
         )
         self.image_url = response.data[0].url
         self.processing, self.complete = False, True
-        
+
 
 def index():
     return rx.center(
@@ -115,7 +114,7 @@ def index():
                 width="25em",
             ),
             rx.button(
-                "Generate Image", 
+                "Generate Image",
                 on_click=State.get_image,
                 width="25em",
                 loading=State.processing
@@ -135,19 +134,12 @@ app = rx.App()
 app.add_page(index, title="Reflex:DALL-E")
 ```
 
-
-
-
-
-
-
 ## 讓我們來拆解一下。
 
 <div align="center">
 <img src="../../images/dalle_colored_code_example.png" alt="解釋 DALL-E app 的前端和後端部分的區別。" width="900" />
 </div>
 
-
 ### **Reflex 使用者介面**
 
 讓我們從使用介面開始。
@@ -161,7 +153,7 @@ def index():
 
 這個 `index` 函式定義了應用程式的前端.
 
-我們用不同的元件像是 `center`, `vstack`, `input`, 和 `button` 來建立前端,元件之間可互相套入以建立出複雜的版面配置。並且您可使用關鍵字引數 *keyword args* 運行 CSS 全部功能來設計這些元件們的樣式。
+我們用不同的元件像是 `center`, `vstack`, `input`, 和 `button` 來建立前端,元件之間可互相套入以建立出複雜的版面配置。並且您可使用關鍵字引數 _keyword args_ 運行 CSS 全部功能來設計這些元件們的樣式。
 
 Reflex 擁有 [60+ 內建元件](https://reflex.dev/docs/library) 來幫助你開始建立應用程式。我們正積極添加元件,你也可以簡單地 [創建自己所屬的元件](https://reflex.dev/docs/wrapping-react/overview/)。
 
@@ -226,12 +218,10 @@ app.add_page(index, title="DALL-E")
 
 <div align="center">
 
-📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; |  &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; |  &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; |  &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; |  &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start)  &nbsp;   
+📑 [Docs](https://reflex.dev/docs/getting-started/introduction) &nbsp; | &nbsp; 🗞️ [Blog](https://reflex.dev/blog) &nbsp; | &nbsp; 📱 [Component Library](https://reflex.dev/docs/library) &nbsp; | &nbsp; 🖼️ [Templates](https://reflex.dev/templates/) &nbsp; | &nbsp; 🛸 [Deployment](https://reflex.dev/docs/hosting/deploy-quick-start) &nbsp;
 
 </div>
 
-
-
 ## ✅ 產品狀態
 
 Reflex 在 2022 年 12 月以 Pynecone 的名字推出。
@@ -244,14 +234,14 @@ Reflex 每周都有新功能和釋出新版本! 確保你按下 :star: 和 :eyes
 
 我們歡迎任何大小的貢獻,以下是一些加入 Reflex 社群的好方法。
 
--   **加入我們的 Discord**: 我們的 [Discord](https://discord.gg/T5WSbC2YtQ) 是獲取 Reflex 專案幫助和討論如何貢獻的最佳地方。
--   **GitHub Discussions**: 這是一個討論您想新增的功能或對於一些困惑/需要澄清事項的好方法。
--   **GitHub Issues**: 在 [Issues](https://github.com/reflex-dev/reflex/issues) 頁面報告錯誤是一個絕佳的方式。此外,您也可以嘗試解決現有 Issue 並提交 PR。
+- **加入我們的 Discord**: 我們的 [Discord](https://discord.gg/T5WSbC2YtQ) 是獲取 Reflex 專案幫助和討論如何貢獻的最佳地方。
+- **GitHub Discussions**: 這是一個討論您想新增的功能或對於一些困惑/需要澄清事項的好方法。
+- **GitHub Issues**: 在 [Issues](https://github.com/reflex-dev/reflex/issues) 頁面報告錯誤是一個絕佳的方式。此外,您也可以嘗試解決現有 Issue 並提交 PR。
 
 我們積極尋找貢獻者,不論您的技能水平或經驗如何。要貢獻,請查看 [CONTRIBUTING.md](https://github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md)
 
-
 ## 感謝所有貢獻者:
+
 <a href="https://github.com/reflex-dev/reflex/graphs/contributors">
   <img src="https://contrib.rocks/image?repo=reflex-dev/reflex" />
 </a>

+ 50 - 0
hatch_build.py

@@ -0,0 +1,50 @@
+"""Custom build hook for Hatch."""
+
+import pathlib
+import subprocess
+import sys
+from typing import Any
+
+from hatchling.builders.hooks.plugin.interface import BuildHookInterface
+
+
+class CustomBuilder(BuildHookInterface):
+    """Custom build hook for Hatch."""
+
+    PLUGIN_NAME = "custom"
+
+    def marker(self) -> pathlib.Path:
+        """Get the marker file path.
+
+        Returns:
+            The marker file path.
+        """
+        return (
+            pathlib.Path(self.directory)
+            / f".reflex-{self.metadata.version}.pyi_generated"
+        )
+
+    def finalize(
+        self, version: str, build_data: dict[str, Any], artifact_path: str
+    ) -> None:
+        """Finalize the build process.
+
+        Args:
+            version: The version of the package.
+            build_data: The build data.
+            artifact_path: The path to the artifact.
+        """
+        if self.marker().exists():
+            return
+
+        if not (pathlib.Path(self.root) / "scripts").exists():
+            return
+
+        for file in (pathlib.Path(self.root) / "reflex").rglob("**/*.pyi"):
+            file.unlink(missing_ok=True)
+
+        subprocess.run(
+            [sys.executable, "-m", "reflex.utils.pyi_generator"],
+            check=True,
+        )
+        self.marker().touch()

+ 0 - 3192
poetry.lock

@@ -1,3192 +0,0 @@
-# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
-
-[[package]]
-name = "alembic"
-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"},
-]
-
-[package.dependencies]
-Mako = "*"
-SQLAlchemy = ">=1.3.0"
-typing-extensions = ">=4"
-
-[package.extras]
-tz = ["backports.zoneinfo", "tzdata"]
-
-[[package]]
-name = "annotated-types"
-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"},
-]
-
-[[package]]
-name = "anyio"
-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"},
-]
-
-[package.dependencies]
-exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""}
-idna = ">=2.8"
-sniffio = ">=1.1"
-typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
-
-[package.extras]
-doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"]
-test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"]
-trio = ["trio (>=0.26.1)"]
-
-[[package]]
-name = "async-timeout"
-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"},
-]
-
-[[package]]
-name = "asynctest"
-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"},
-]
-
-[[package]]
-name = "attrs"
-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-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"},
-    {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"},
-]
-
-[package.extras]
-benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
-cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
-dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
-docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
-tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
-tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
-
-[[package]]
-name = "backports-tarfile"
-version = "1.2.0"
-description = "Backport of CPython tarfile module"
-optional = false
-python-versions = ">=3.8"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\")"
-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"},
-]
-
-[package.extras]
-docs = ["furo", "jaraco.packaging (>=9.3)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-testing = ["jaraco.test", "pytest (!=8.0.*)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)"]
-
-[[package]]
-name = "bidict"
-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"},
-]
-
-[[package]]
-name = "build"
-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"},
-]
-
-[package.dependencies]
-colorama = {version = "*", markers = "os_name == \"nt\""}
-importlib-metadata = {version = ">=4.6", markers = "python_full_version < \"3.10.2\""}
-packaging = ">=19.1"
-pyproject_hooks = "*"
-tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-
-[package.extras]
-docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"]
-test = ["build[uv,virtualenv]", "filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"]
-typing = ["build[uv]", "importlib-metadata (>=5.1)", "mypy (>=1.9.0,<1.10.0)", "tomli", "typing-extensions (>=3.7.4.3)"]
-uv = ["uv (>=0.1.18)"]
-virtualenv = ["virtualenv (>=20.0.35)"]
-
-[[package]]
-name = "certifi"
-version = "2025.1.31"
-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-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"},
-    {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"},
-]
-
-[[package]]
-name = "cffi"
-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"},
-    {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"},
-    {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"},
-    {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"},
-    {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"},
-    {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"},
-    {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"},
-    {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"},
-    {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"},
-    {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"},
-    {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"},
-    {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"},
-    {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"},
-    {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"},
-    {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"},
-    {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"},
-    {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"},
-    {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"},
-    {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"},
-    {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"},
-    {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"},
-    {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"},
-    {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"},
-    {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"},
-    {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"},
-    {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"},
-    {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"},
-    {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"},
-    {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"},
-    {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"},
-    {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"},
-    {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"},
-    {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"},
-    {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"},
-    {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"},
-    {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"},
-    {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"},
-    {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"},
-    {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"},
-    {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"},
-    {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"},
-    {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"},
-    {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"},
-    {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"},
-    {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"},
-    {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"},
-    {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"},
-    {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"},
-    {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"},
-    {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"},
-    {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"},
-    {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"},
-    {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"},
-    {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"},
-    {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"},
-    {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"},
-    {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"},
-    {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"},
-    {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"},
-    {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"},
-    {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"},
-    {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"},
-    {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"},
-    {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"},
-    {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 = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" and platform_python_implementation != \"PyPy\" or python_version >= \"3.12\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" and platform_python_implementation != \"PyPy\"", dev = "python_version <= \"3.11\" or python_version >= \"3.12\""}
-
-[package.dependencies]
-pycparser = "*"
-
-[[package]]
-name = "cfgv"
-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"},
-]
-
-[[package]]
-name = "charset-normalizer"
-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"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"},
-    {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"},
-    {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"},
-    {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"},
-    {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"},
-    {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"},
-    {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"},
-    {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"},
-    {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"},
-    {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"},
-]
-
-[[package]]
-name = "click"
-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"},
-]
-
-[package.dependencies]
-colorama = {version = "*", markers = "platform_system == \"Windows\""}
-
-[[package]]
-name = "colorama"
-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 = "python_version <= \"3.11\" and platform_system == \"Windows\" or python_version <= \"3.11\" and os_name == \"nt\" or python_version >= \"3.12\" and platform_system == \"Windows\" or python_version >= \"3.12\" and os_name == \"nt\"", dev = "python_version <= \"3.11\" and sys_platform == \"win32\" or python_version >= \"3.12\" and sys_platform == \"win32\""}
-
-[[package]]
-name = "coverage"
-version = "7.6.12"
-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.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:704c8c8c6ce6569286ae9622e534b4f5b9759b6f2cd643f1c1a61f666d534fe8"},
-    {file = "coverage-7.6.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ad7525bf0241e5502168ae9c643a2f6c219fa0a283001cee4cf23a9b7da75879"},
-    {file = "coverage-7.6.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06097c7abfa611c91edb9e6920264e5be1d6ceb374efb4986f38b09eed4cb2fe"},
-    {file = "coverage-7.6.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:220fa6c0ad7d9caef57f2c8771918324563ef0d8272c94974717c3909664e674"},
-    {file = "coverage-7.6.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3688b99604a24492bcfe1c106278c45586eb819bf66a654d8a9a1433022fb2eb"},
-    {file = "coverage-7.6.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d1a987778b9c71da2fc8948e6f2656da6ef68f59298b7e9786849634c35d2c3c"},
-    {file = "coverage-7.6.12-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:cec6b9ce3bd2b7853d4a4563801292bfee40b030c05a3d29555fd2a8ee9bd68c"},
-    {file = "coverage-7.6.12-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ace9048de91293e467b44bce0f0381345078389814ff6e18dbac8fdbf896360e"},
-    {file = "coverage-7.6.12-cp310-cp310-win32.whl", hash = "sha256:ea31689f05043d520113e0552f039603c4dd71fa4c287b64cb3606140c66f425"},
-    {file = "coverage-7.6.12-cp310-cp310-win_amd64.whl", hash = "sha256:676f92141e3c5492d2a1596d52287d0d963df21bf5e55c8b03075a60e1ddf8aa"},
-    {file = "coverage-7.6.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e18aafdfb3e9ec0d261c942d35bd7c28d031c5855dadb491d2723ba54f4c3015"},
-    {file = "coverage-7.6.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66fe626fd7aa5982cdebad23e49e78ef7dbb3e3c2a5960a2b53632f1f703ea45"},
-    {file = "coverage-7.6.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ef01d70198431719af0b1f5dcbefc557d44a190e749004042927b2a3fed0702"},
-    {file = "coverage-7.6.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e92ae5a289a4bc4c0aae710c0948d3c7892e20fd3588224ebe242039573bf0"},
-    {file = "coverage-7.6.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e695df2c58ce526eeab11a2e915448d3eb76f75dffe338ea613c1201b33bab2f"},
-    {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d74c08e9aaef995f8c4ef6d202dbd219c318450fe2a76da624f2ebb9c8ec5d9f"},
-    {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e995b3b76ccedc27fe4f477b349b7d64597e53a43fc2961db9d3fbace085d69d"},
-    {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b1f097878d74fe51e1ddd1be62d8e3682748875b461232cf4b52ddc6e6db0bba"},
-    {file = "coverage-7.6.12-cp311-cp311-win32.whl", hash = "sha256:1f7ffa05da41754e20512202c866d0ebfc440bba3b0ed15133070e20bf5aeb5f"},
-    {file = "coverage-7.6.12-cp311-cp311-win_amd64.whl", hash = "sha256:e216c5c45f89ef8971373fd1c5d8d1164b81f7f5f06bbf23c37e7908d19e8558"},
-    {file = "coverage-7.6.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b172f8e030e8ef247b3104902cc671e20df80163b60a203653150d2fc204d1ad"},
-    {file = "coverage-7.6.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:641dfe0ab73deb7069fb972d4d9725bf11c239c309ce694dd50b1473c0f641c3"},
-    {file = "coverage-7.6.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e549f54ac5f301e8e04c569dfdb907f7be71b06b88b5063ce9d6953d2d58574"},
-    {file = "coverage-7.6.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:959244a17184515f8c52dcb65fb662808767c0bd233c1d8a166e7cf74c9ea985"},
-    {file = "coverage-7.6.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bda1c5f347550c359f841d6614fb8ca42ae5cb0b74d39f8a1e204815ebe25750"},
-    {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ceeb90c3eda1f2d8c4c578c14167dbd8c674ecd7d38e45647543f19839dd6ea"},
-    {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f16f44025c06792e0fb09571ae454bcc7a3ec75eeb3c36b025eccf501b1a4c3"},
-    {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b076e625396e787448d27a411aefff867db2bffac8ed04e8f7056b07024eed5a"},
-    {file = "coverage-7.6.12-cp312-cp312-win32.whl", hash = "sha256:00b2086892cf06c7c2d74983c9595dc511acca00665480b3ddff749ec4fb2a95"},
-    {file = "coverage-7.6.12-cp312-cp312-win_amd64.whl", hash = "sha256:7ae6eabf519bc7871ce117fb18bf14e0e343eeb96c377667e3e5dd12095e0288"},
-    {file = "coverage-7.6.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:488c27b3db0ebee97a830e6b5a3ea930c4a6e2c07f27a5e67e1b3532e76b9ef1"},
-    {file = "coverage-7.6.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d1095bbee1851269f79fd8e0c9b5544e4c00c0c24965e66d8cba2eb5bb535fd"},
-    {file = "coverage-7.6.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0533adc29adf6a69c1baa88c3d7dbcaadcffa21afbed3ca7a225a440e4744bf9"},
-    {file = "coverage-7.6.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53c56358d470fa507a2b6e67a68fd002364d23c83741dbc4c2e0680d80ca227e"},
-    {file = "coverage-7.6.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64cbb1a3027c79ca6310bf101014614f6e6e18c226474606cf725238cf5bc2d4"},
-    {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:79cac3390bfa9836bb795be377395f28410811c9066bc4eefd8015258a7578c6"},
-    {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9b148068e881faa26d878ff63e79650e208e95cf1c22bd3f77c3ca7b1d9821a3"},
-    {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8bec2ac5da793c2685ce5319ca9bcf4eee683b8a1679051f8e6ec04c4f2fd7dc"},
-    {file = "coverage-7.6.12-cp313-cp313-win32.whl", hash = "sha256:200e10beb6ddd7c3ded322a4186313d5ca9e63e33d8fab4faa67ef46d3460af3"},
-    {file = "coverage-7.6.12-cp313-cp313-win_amd64.whl", hash = "sha256:2b996819ced9f7dbb812c701485d58f261bef08f9b85304d41219b1496b591ef"},
-    {file = "coverage-7.6.12-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:299cf973a7abff87a30609879c10df0b3bfc33d021e1adabc29138a48888841e"},
-    {file = "coverage-7.6.12-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4b467a8c56974bf06e543e69ad803c6865249d7a5ccf6980457ed2bc50312703"},
-    {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2458f275944db8129f95d91aee32c828a408481ecde3b30af31d552c2ce284a0"},
-    {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a9d8be07fb0832636a0f72b80d2a652fe665e80e720301fb22b191c3434d924"},
-    {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d47376a4f445e9743f6c83291e60adb1b127607a3618e3185bbc8091f0467b"},
-    {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b95574d06aa9d2bd6e5cc35a5bbe35696342c96760b69dc4287dbd5abd4ad51d"},
-    {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ecea0c38c9079570163d663c0433a9af4094a60aafdca491c6a3d248c7432827"},
-    {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2251fabcfee0a55a8578a9d29cecfee5f2de02f11530e7d5c5a05859aa85aee9"},
-    {file = "coverage-7.6.12-cp313-cp313t-win32.whl", hash = "sha256:eb5507795caabd9b2ae3f1adc95f67b1104971c22c624bb354232d65c4fc90b3"},
-    {file = "coverage-7.6.12-cp313-cp313t-win_amd64.whl", hash = "sha256:f60a297c3987c6c02ffb29effc70eadcbb412fe76947d394a1091a3615948e2f"},
-    {file = "coverage-7.6.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e7575ab65ca8399c8c4f9a7d61bbd2d204c8b8e447aab9d355682205c9dd948d"},
-    {file = "coverage-7.6.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8161d9fbc7e9fe2326de89cd0abb9f3599bccc1287db0aba285cb68d204ce929"},
-    {file = "coverage-7.6.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a1e465f398c713f1b212400b4e79a09829cd42aebd360362cd89c5bdc44eb87"},
-    {file = "coverage-7.6.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f25d8b92a4e31ff1bd873654ec367ae811b3a943583e05432ea29264782dc32c"},
-    {file = "coverage-7.6.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a936309a65cc5ca80fa9f20a442ff9e2d06927ec9a4f54bcba9c14c066323f2"},
-    {file = "coverage-7.6.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:aa6f302a3a0b5f240ee201297fff0bbfe2fa0d415a94aeb257d8b461032389bd"},
-    {file = "coverage-7.6.12-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f973643ef532d4f9be71dd88cf7588936685fdb576d93a79fe9f65bc337d9d73"},
-    {file = "coverage-7.6.12-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:78f5243bb6b1060aed6213d5107744c19f9571ec76d54c99cc15938eb69e0e86"},
-    {file = "coverage-7.6.12-cp39-cp39-win32.whl", hash = "sha256:69e62c5034291c845fc4df7f8155e8544178b6c774f97a99e2734b05eb5bed31"},
-    {file = "coverage-7.6.12-cp39-cp39-win_amd64.whl", hash = "sha256:b01a840ecc25dce235ae4c1b6a0daefb2a203dba0e6e980637ee9c2f6ee0df57"},
-    {file = "coverage-7.6.12-pp39.pp310-none-any.whl", hash = "sha256:7e39e845c4d764208e7b8f6a21c541ade741e2c41afabdfa1caa28687a3c98cf"},
-    {file = "coverage-7.6.12-py3-none-any.whl", hash = "sha256:eb8668cfbc279a536c633137deeb9435d2962caec279c3f8cf8b91fff6ff8953"},
-    {file = "coverage-7.6.12.tar.gz", hash = "sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2"},
-]
-
-[package.dependencies]
-tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
-
-[package.extras]
-toml = ["tomli"]
-
-[[package]]
-name = "cryptography"
-version = "44.0.1"
-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 = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" or python_version >= \"3.12\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\""
-files = [
-    {file = "cryptography-44.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009"},
-    {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f"},
-    {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887143b9ff6bad2b7570da75a7fe8bbf5f65276365ac259a5d2d5147a73775f2"},
-    {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:322eb03ecc62784536bc173f1483e76747aafeb69c8728df48537eb431cd1911"},
-    {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:21377472ca4ada2906bc313168c9dc7b1d7ca417b63c1c3011d0c74b7de9ae69"},
-    {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df978682c1504fc93b3209de21aeabf2375cb1571d4e61907b3e7a2540e83026"},
-    {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:eb3889330f2a4a148abead555399ec9a32b13b7c8ba969b72d8e500eb7ef84cd"},
-    {file = "cryptography-44.0.1-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:8e6a85a93d0642bd774460a86513c5d9d80b5c002ca9693e63f6e540f1815ed0"},
-    {file = "cryptography-44.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6f76fdd6fd048576a04c5210d53aa04ca34d2ed63336d4abd306d0cbe298fddf"},
-    {file = "cryptography-44.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6c8acf6f3d1f47acb2248ec3ea261171a671f3d9428e34ad0357148d492c7864"},
-    {file = "cryptography-44.0.1-cp37-abi3-win32.whl", hash = "sha256:24979e9f2040c953a94bf3c6782e67795a4c260734e5264dceea65c8f4bae64a"},
-    {file = "cryptography-44.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:fd0ee90072861e276b0ff08bd627abec29e32a53b2be44e41dbcdf87cbee2b00"},
-    {file = "cryptography-44.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a2d8a7045e1ab9b9f803f0d9531ead85f90c5f2859e653b61497228b18452008"},
-    {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8272f257cf1cbd3f2e120f14c68bff2b6bdfcc157fafdee84a1b795efd72862"},
-    {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e8d181e90a777b63f3f0caa836844a1182f1f265687fac2115fcf245f5fbec3"},
-    {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:436df4f203482f41aad60ed1813811ac4ab102765ecae7a2bbb1dbb66dcff5a7"},
-    {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4f422e8c6a28cf8b7f883eb790695d6d45b0c385a2583073f3cec434cc705e1a"},
-    {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:72198e2b5925155497a5a3e8c216c7fb3e64c16ccee11f0e7da272fa93b35c4c"},
-    {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a46a89ad3e6176223b632056f321bc7de36b9f9b93b2cc1cccf935a3849dc62"},
-    {file = "cryptography-44.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:53f23339864b617a3dfc2b0ac8d5c432625c80014c25caac9082314e9de56f41"},
-    {file = "cryptography-44.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:888fcc3fce0c888785a4876ca55f9f43787f4c5c1cc1e2e0da71ad481ff82c5b"},
-    {file = "cryptography-44.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00918d859aa4e57db8299607086f793fa7813ae2ff5a4637e318a25ef82730f7"},
-    {file = "cryptography-44.0.1-cp39-abi3-win32.whl", hash = "sha256:9b336599e2cb77b1008cb2ac264b290803ec5e8e89d618a5e978ff5eb6f715d9"},
-    {file = "cryptography-44.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:e403f7f766ded778ecdb790da786b418a9f2394f36e8cc8b796cc056ab05f44f"},
-    {file = "cryptography-44.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1f9a92144fa0c877117e9748c74501bea842f93d21ee00b0cf922846d9d0b183"},
-    {file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:610a83540765a8d8ce0f351ce42e26e53e1f774a6efb71eb1b41eb01d01c3d12"},
-    {file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5fed5cd6102bb4eb843e3315d2bf25fede494509bddadb81e03a859c1bc17b83"},
-    {file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:f4daefc971c2d1f82f03097dc6f216744a6cd2ac0f04c68fb935ea2ba2a0d420"},
-    {file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:94f99f2b943b354a5b6307d7e8d19f5c423a794462bde2bf310c770ba052b1c4"},
-    {file = "cryptography-44.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d9c5b9f698a83c8bd71e0f4d3f9f839ef244798e5ffe96febfa9714717db7af7"},
-    {file = "cryptography-44.0.1.tar.gz", hash = "sha256:f51f5705ab27898afda1aaa430f34ad90dc117421057782022edf0600bec5f14"},
-]
-
-[package.dependencies]
-cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""}
-
-[package.extras]
-docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"]
-docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"]
-nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"]
-pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"]
-sdist = ["build (>=1.0.0)"]
-ssh = ["bcrypt (>=3.1.5)"]
-test = ["certifi (>=2024)", "cryptography-vectors (==44.0.1)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
-test-randomorder = ["pytest-randomly"]
-
-[[package]]
-name = "darglint"
-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"},
-]
-
-[[package]]
-name = "dill"
-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"},
-]
-
-[package.extras]
-graph = ["objgraph (>=1.7.2)"]
-profile = ["gprof2dot (>=2022.7.29)"]
-
-[[package]]
-name = "distlib"
-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"},
-]
-
-[[package]]
-name = "distro"
-version = "1.9.0"
-description = "Distro - an OS platform information API"
-optional = false
-python-versions = ">=3.6"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and sys_platform == \"linux\" 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"},
-]
-
-[[package]]
-name = "docutils"
-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"},
-]
-
-[[package]]
-name = "exceptiongroup"
-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"},
-]
-
-[package.extras]
-test = ["pytest (>=6)"]
-
-[[package]]
-name = "fastapi"
-version = "0.115.8"
-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.8-py3-none-any.whl", hash = "sha256:753a96dd7e036b34eeef8babdfcfe3f28ff79648f86551eb36bfc1b0bf4a8cbf"},
-    {file = "fastapi-0.115.8.tar.gz", hash = "sha256:0ce9111231720190473e222cdf0f07f7206ad7e53ea02beb1d2dc36e2f0741e9"},
-]
-
-[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.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 (>=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"
-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"},
-]
-
-[package.extras]
-docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"]
-testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"]
-typing = ["typing-extensions (>=4.12.2)"]
-
-[[package]]
-name = "greenlet"
-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"},
-    {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"},
-]
-markers = {main = "python_version <= \"3.11\" 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\") or python_version >= \"3.12\" and 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\")", dev = "python_version <= \"3.11\" or python_version >= \"3.12\""}
-
-[package.extras]
-docs = ["Sphinx", "furo"]
-test = ["objgraph", "psutil"]
-
-[[package]]
-name = "gunicorn"
-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"},
-]
-
-[package.dependencies]
-packaging = "*"
-
-[package.extras]
-eventlet = ["eventlet (>=0.24.1,!=0.36.0)"]
-gevent = ["gevent (>=1.4.0)"]
-setproctitle = ["setproctitle"]
-testing = ["coverage", "eventlet", "gevent", "pytest", "pytest-cov"]
-tornado = ["tornado (>=0.2)"]
-
-[[package]]
-name = "h11"
-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"},
-]
-
-[[package]]
-name = "httpcore"
-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"},
-]
-
-[package.dependencies]
-certifi = "*"
-h11 = ">=0.13,<0.15"
-
-[package.extras]
-asyncio = ["anyio (>=4.0,<5.0)"]
-http2 = ["h2 (>=3,<5)"]
-socks = ["socksio (==1.*)"]
-trio = ["trio (>=0.22.0,<1.0)"]
-
-[[package]]
-name = "httpx"
-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"},
-]
-
-[package.dependencies]
-anyio = "*"
-certifi = "*"
-httpcore = "==1.*"
-idna = "*"
-
-[package.extras]
-brotli = ["brotli", "brotlicffi"]
-cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
-http2 = ["h2 (>=3,<5)"]
-socks = ["socksio (==1.*)"]
-zstd = ["zstandard (>=0.18.0)"]
-
-[[package]]
-name = "id"
-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"},
-]
-
-[package.dependencies]
-requests = "*"
-
-[package.extras]
-dev = ["build", "bump (>=1.3.2)", "id[lint,test]"]
-lint = ["bandit", "interrogate", "mypy", "ruff (<0.8.2)", "types-requests"]
-test = ["coverage[toml]", "pretend", "pytest", "pytest-cov"]
-
-[[package]]
-name = "identify"
-version = "2.6.7"
-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.7-py2.py3-none-any.whl", hash = "sha256:155931cb617a401807b09ecec6635d6c692d180090a1cedca8ef7d58ba5b6aa0"},
-    {file = "identify-2.6.7.tar.gz", hash = "sha256:3fa266b42eba321ee0b2bb0936a6a6b9e36a1351cbb69055b3082f4193035684"},
-]
-
-[package.extras]
-license = ["ukkonen"]
-
-[[package]]
-name = "idna"
-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"},
-]
-
-[package.extras]
-all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
-
-[[package]]
-name = "importlib-metadata"
-version = "8.6.1"
-description = "Read metadata from Python packages"
-optional = false
-python-versions = ">=3.9"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") 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"},
-]
-
-[package.dependencies]
-zipp = ">=3.20"
-
-[package.extras]
-check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
-cover = ["pytest-cov"]
-doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-enabler = ["pytest-enabler (>=2.2)"]
-perf = ["ipython"]
-test = ["flufl.flake8", "importlib_resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
-type = ["pytest-mypy"]
-
-[[package]]
-name = "iniconfig"
-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"},
-]
-
-[[package]]
-name = "jaraco-classes"
-version = "3.4.0"
-description = "Utility functions for Python class constructs"
-optional = false
-python-versions = ">=3.8"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") 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"},
-]
-
-[package.dependencies]
-more-itertools = "*"
-
-[package.extras]
-docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
-
-[[package]]
-name = "jaraco-context"
-version = "6.0.1"
-description = "Useful decorators and context managers"
-optional = false
-python-versions = ">=3.8"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") 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"},
-]
-
-[package.dependencies]
-"backports.tarfile" = {version = "*", markers = "python_version < \"3.12\""}
-
-[package.extras]
-doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-test = ["portend", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
-
-[[package]]
-name = "jaraco-functools"
-version = "4.1.0"
-description = "Functools like those found in stdlib"
-optional = false
-python-versions = ">=3.8"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") 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"},
-]
-
-[package.dependencies]
-more-itertools = "*"
-
-[package.extras]
-check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
-cover = ["pytest-cov"]
-doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-enabler = ["pytest-enabler (>=2.2)"]
-test = ["jaraco.classes", "pytest (>=6,!=8.1.*)"]
-type = ["pytest-mypy"]
-
-[[package]]
-name = "jeepney"
-version = "0.8.0"
-description = "Low-level, pure Python DBus protocol wrapper."
-optional = false
-python-versions = ">=3.7"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" or python_version >= \"3.12\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\""
-files = [
-    {file = "jeepney-0.8.0-py3-none-any.whl", hash = "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755"},
-    {file = "jeepney-0.8.0.tar.gz", hash = "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806"},
-]
-
-[package.extras]
-test = ["async-timeout", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"]
-trio = ["async_generator", "trio"]
-
-[[package]]
-name = "jinja2"
-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"},
-]
-
-[package.dependencies]
-MarkupSafe = ">=2.0"
-
-[package.extras]
-i18n = ["Babel (>=2.7)"]
-
-[[package]]
-name = "keyring"
-version = "25.6.0"
-description = "Store and access your passwords safely."
-optional = false
-python-versions = ">=3.9"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") 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"},
-]
-
-[package.dependencies]
-importlib_metadata = {version = ">=4.11.4", markers = "python_version < \"3.12\""}
-"jaraco.classes" = "*"
-"jaraco.context" = "*"
-"jaraco.functools" = "*"
-jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""}
-pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""}
-SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""}
-
-[package.extras]
-check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
-completion = ["shtab (>=1.1.0)"]
-cover = ["pytest-cov"]
-doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-enabler = ["pytest-enabler (>=2.2)"]
-test = ["pyfakefs", "pytest (>=6,!=8.1.*)"]
-type = ["pygobject-stubs", "pytest-mypy", "shtab", "types-pywin32"]
-
-[[package]]
-name = "lazy-loader"
-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"},
-]
-
-[package.dependencies]
-packaging = "*"
-
-[package.extras]
-dev = ["changelist (==0.5)"]
-lint = ["pre-commit (==3.7.0)"]
-test = ["pytest (>=7.4)", "pytest-cov (>=4.1)"]
-
-[[package]]
-name = "mako"
-version = "1.3.9"
-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.9-py3-none-any.whl", hash = "sha256:95920acccb578427a9aa38e37a186b1e43156c87260d7ba18ca63aa4c7cbd3a1"},
-    {file = "mako-1.3.9.tar.gz", hash = "sha256:b5d65ff3462870feec922dbccf38f6efb44e5714d7b593a656be86663d8600ac"},
-]
-
-[package.dependencies]
-MarkupSafe = ">=0.9.2"
-
-[package.extras]
-babel = ["Babel"]
-lingua = ["lingua"]
-testing = ["pytest"]
-
-[[package]]
-name = "markdown-it-py"
-version = "3.0.0"
-description = "Python port of markdown-it. Markdown parsing, done right!"
-optional = false
-python-versions = ">=3.8"
-groups = ["main", "dev"]
-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"},
-]
-
-[package.dependencies]
-mdurl = ">=0.1,<1.0"
-
-[package.extras]
-benchmarking = ["psutil", "pytest", "pytest-benchmark"]
-code-style = ["pre-commit (>=3.0,<4.0)"]
-compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
-linkify = ["linkify-it-py (>=1,<3)"]
-plugins = ["mdit-py-plugins"]
-profiling = ["gprof2dot"]
-rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
-testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
-
-[[package]]
-name = "markupsafe"
-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"},
-    {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"},
-    {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"},
-    {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"},
-    {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"},
-    {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"},
-    {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"},
-    {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"},
-    {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"},
-    {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"},
-    {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"},
-    {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"},
-    {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"},
-    {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"},
-    {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"},
-    {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"},
-    {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"},
-    {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"},
-    {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"},
-    {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"},
-    {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"},
-    {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"},
-    {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"},
-    {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"},
-    {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"},
-    {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"},
-    {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"},
-    {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"},
-    {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"},
-    {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"},
-    {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"},
-    {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"},
-    {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"},
-    {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"},
-    {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"},
-    {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"},
-    {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"},
-    {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"},
-    {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"},
-    {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"},
-    {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"},
-]
-
-[[package]]
-name = "mdurl"
-version = "0.1.2"
-description = "Markdown URL utilities"
-optional = false
-python-versions = ">=3.7"
-groups = ["main", "dev"]
-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"},
-]
-
-[[package]]
-name = "more-itertools"
-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\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") 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"},
-]
-
-[[package]]
-name = "nh3"
-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"},
-    {file = "nh3-0.2.20-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ae9cbd713524cdb81e64663d0d6aae26f678db9f2cd9db0bf162606f1f9f20c"},
-    {file = "nh3-0.2.20-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e1f7370b4e14cc03f5ae141ef30a1caf81fa5787711f80be9081418dd9eb79d2"},
-    {file = "nh3-0.2.20-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:ac4d27dc836a476efffc6eb661994426b8b805c951b29c9cf2ff36bc9ad58bc5"},
-    {file = "nh3-0.2.20-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4fd2e9248725ebcedac3997a8d3da0d90a12a28c9179c6ba51f1658938ac30d0"},
-    {file = "nh3-0.2.20-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f7d564871833ddbe54df3aa59053b1110729d3a800cb7628ae8f42adb3d75208"},
-    {file = "nh3-0.2.20-cp313-cp313t-win32.whl", hash = "sha256:d2a176fd4306b6f0f178a3f67fac91bd97a3a8d8fafb771c9b9ef675ba5c8886"},
-    {file = "nh3-0.2.20-cp313-cp313t-win_amd64.whl", hash = "sha256:6ed834c68452a600f517dd3e1534dbfaff1f67f98899fecf139a055a25d99150"},
-    {file = "nh3-0.2.20-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:76e2f603b30c02ff6456b233a83fc377dedab6a50947b04e960a6b905637b776"},
-    {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:181063c581defe683bd4bb78188ac9936d208aebbc74c7f7c16b6a32ae2ebb38"},
-    {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:231addb7643c952cd6d71f1c8702d703f8fe34afcb20becb3efb319a501a12d7"},
-    {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1b9a8340a0aab991c68a5ca938d35ef4a8a3f4bf1b455da8855a40bee1fa0ace"},
-    {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10317cd96fe4bbd4eb6b95f3920b71c902157ad44fed103fdcde43e3b8ee8be6"},
-    {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8698db4c04b140800d1a1cd3067fda399e36e1e2b8fc1fe04292a907350a3e9b"},
-    {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eb04b9c3deb13c3a375ea39fd4a3c00d1f92e8fb2349f25f1e3e4506751774b"},
-    {file = "nh3-0.2.20-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92f3f1c4f47a2c6f3ca7317b1d5ced05bd29556a75d3a4e2715652ae9d15c05d"},
-    {file = "nh3-0.2.20-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ddefa9fd6794a87e37d05827d299d4b53a3ec6f23258101907b96029bfef138a"},
-    {file = "nh3-0.2.20-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:ce3731c8f217685d33d9268362e5b4f770914e922bba94d368ab244a59a6c397"},
-    {file = "nh3-0.2.20-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:09f037c02fc2c43b211ff1523de32801dcfb0918648d8e651c36ef890f1731ec"},
-    {file = "nh3-0.2.20-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:813f1c8012dd64c990514b795508abb90789334f76a561fa0fd4ca32d2275330"},
-    {file = "nh3-0.2.20-cp38-abi3-win32.whl", hash = "sha256:47b2946c0e13057855209daeffb45dc910bd0c55daf10190bb0b4b60e2999784"},
-    {file = "nh3-0.2.20-cp38-abi3-win_amd64.whl", hash = "sha256:da87573f03084edae8eb87cfe811ec338606288f81d333c07d2a9a0b9b976c0b"},
-    {file = "nh3-0.2.20.tar.gz", hash = "sha256:9705c42d7ff88a0bea546c82d7fe5e59135e3d3f057e485394f491248a1f8ed5"},
-]
-
-[[package]]
-name = "nodeenv"
-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"},
-]
-
-[[package]]
-name = "numpy"
-version = "2.2.3"
-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.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cbc6472e01952d3d1b2772b720428f8b90e2deea8344e854df22b0618e9cce71"},
-    {file = "numpy-2.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cdfe0c22692a30cd830c0755746473ae66c4a8f2e7bd508b35fb3b6a0813d787"},
-    {file = "numpy-2.2.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:e37242f5324ffd9f7ba5acf96d774f9276aa62a966c0bad8dae692deebec7716"},
-    {file = "numpy-2.2.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:95172a21038c9b423e68be78fd0be6e1b97674cde269b76fe269a5dfa6fadf0b"},
-    {file = "numpy-2.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b47c440210c5d1d67e1cf434124e0b5c395eee1f5806fdd89b553ed1acd0a3"},
-    {file = "numpy-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0391ea3622f5c51a2e29708877d56e3d276827ac5447d7f45e9bc4ade8923c52"},
-    {file = "numpy-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f6b3dfc7661f8842babd8ea07e9897fe3d9b69a1d7e5fbb743e4160f9387833b"},
-    {file = "numpy-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1ad78ce7f18ce4e7df1b2ea4019b5817a2f6a8a16e34ff2775f646adce0a5027"},
-    {file = "numpy-2.2.3-cp310-cp310-win32.whl", hash = "sha256:5ebeb7ef54a7be11044c33a17b2624abe4307a75893c001a4800857956b41094"},
-    {file = "numpy-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:596140185c7fa113563c67c2e894eabe0daea18cf8e33851738c19f70ce86aeb"},
-    {file = "numpy-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:16372619ee728ed67a2a606a614f56d3eabc5b86f8b615c79d01957062826ca8"},
-    {file = "numpy-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5521a06a3148686d9269c53b09f7d399a5725c47bbb5b35747e1cb76326b714b"},
-    {file = "numpy-2.2.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:7c8dde0ca2f77828815fd1aedfdf52e59071a5bae30dac3b4da2a335c672149a"},
-    {file = "numpy-2.2.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:77974aba6c1bc26e3c205c2214f0d5b4305bdc719268b93e768ddb17e3fdd636"},
-    {file = "numpy-2.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d42f9c36d06440e34226e8bd65ff065ca0963aeecada587b937011efa02cdc9d"},
-    {file = "numpy-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2712c5179f40af9ddc8f6727f2bd910ea0eb50206daea75f58ddd9fa3f715bb"},
-    {file = "numpy-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c8b0451d2ec95010d1db8ca733afc41f659f425b7f608af569711097fd6014e2"},
-    {file = "numpy-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9b4a8148c57ecac25a16b0e11798cbe88edf5237b0df99973687dd866f05e1b"},
-    {file = "numpy-2.2.3-cp311-cp311-win32.whl", hash = "sha256:1f45315b2dc58d8a3e7754fe4e38b6fce132dab284a92851e41b2b344f6441c5"},
-    {file = "numpy-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f48ba6f6c13e5e49f3d3efb1b51c8193215c42ac82610a04624906a9270be6f"},
-    {file = "numpy-2.2.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12c045f43b1d2915eca6b880a7f4a256f59d62df4f044788c8ba67709412128d"},
-    {file = "numpy-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:87eed225fd415bbae787f93a457af7f5990b92a334e346f72070bf569b9c9c95"},
-    {file = "numpy-2.2.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:712a64103d97c404e87d4d7c47fb0c7ff9acccc625ca2002848e0d53288b90ea"},
-    {file = "numpy-2.2.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a5ae282abe60a2db0fd407072aff4599c279bcd6e9a2475500fc35b00a57c532"},
-    {file = "numpy-2.2.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5266de33d4c3420973cf9ae3b98b54a2a6d53a559310e3236c4b2b06b9c07d4e"},
-    {file = "numpy-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b787adbf04b0db1967798dba8da1af07e387908ed1553a0d6e74c084d1ceafe"},
-    {file = "numpy-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:34c1b7e83f94f3b564b35f480f5652a47007dd91f7c839f404d03279cc8dd021"},
-    {file = "numpy-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4d8335b5f1b6e2bce120d55fb17064b0262ff29b459e8493d1785c18ae2553b8"},
-    {file = "numpy-2.2.3-cp312-cp312-win32.whl", hash = "sha256:4d9828d25fb246bedd31e04c9e75714a4087211ac348cb39c8c5f99dbb6683fe"},
-    {file = "numpy-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:83807d445817326b4bcdaaaf8e8e9f1753da04341eceec705c001ff342002e5d"},
-    {file = "numpy-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bfdb06b395385ea9b91bf55c1adf1b297c9fdb531552845ff1d3ea6e40d5aba"},
-    {file = "numpy-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:23c9f4edbf4c065fddb10a4f6e8b6a244342d95966a48820c614891e5059bb50"},
-    {file = "numpy-2.2.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:a0c03b6be48aaf92525cccf393265e02773be8fd9551a2f9adbe7db1fa2b60f1"},
-    {file = "numpy-2.2.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:2376e317111daa0a6739e50f7ee2a6353f768489102308b0d98fcf4a04f7f3b5"},
-    {file = "numpy-2.2.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fb62fe3d206d72fe1cfe31c4a1106ad2b136fcc1606093aeab314f02930fdf2"},
-    {file = "numpy-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52659ad2534427dffcc36aac76bebdd02b67e3b7a619ac67543bc9bfe6b7cdb1"},
-    {file = "numpy-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1b416af7d0ed3271cad0f0a0d0bee0911ed7eba23e66f8424d9f3dfcdcae1304"},
-    {file = "numpy-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1402da8e0f435991983d0a9708b779f95a8c98c6b18a171b9f1be09005e64d9d"},
-    {file = "numpy-2.2.3-cp313-cp313-win32.whl", hash = "sha256:136553f123ee2951bfcfbc264acd34a2fc2f29d7cdf610ce7daf672b6fbaa693"},
-    {file = "numpy-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:5b732c8beef1d7bc2d9e476dbba20aaff6167bf205ad9aa8d30913859e82884b"},
-    {file = "numpy-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:435e7a933b9fda8126130b046975a968cc2d833b505475e588339e09f7672890"},
-    {file = "numpy-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7678556eeb0152cbd1522b684dcd215250885993dd00adb93679ec3c0e6e091c"},
-    {file = "numpy-2.2.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:2e8da03bd561504d9b20e7a12340870dfc206c64ea59b4cfee9fceb95070ee94"},
-    {file = "numpy-2.2.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:c9aa4496fd0e17e3843399f533d62857cef5900facf93e735ef65aa4bbc90ef0"},
-    {file = "numpy-2.2.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4ca91d61a4bf61b0f2228f24bbfa6a9facd5f8af03759fe2a655c50ae2c6610"},
-    {file = "numpy-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deaa09cd492e24fd9b15296844c0ad1b3c976da7907e1c1ed3a0ad21dded6f76"},
-    {file = "numpy-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:246535e2f7496b7ac85deffe932896a3577be7af8fb7eebe7146444680297e9a"},
-    {file = "numpy-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:daf43a3d1ea699402c5a850e5313680ac355b4adc9770cd5cfc2940e7861f1bf"},
-    {file = "numpy-2.2.3-cp313-cp313t-win32.whl", hash = "sha256:cf802eef1f0134afb81fef94020351be4fe1d6681aadf9c5e862af6602af64ef"},
-    {file = "numpy-2.2.3-cp313-cp313t-win_amd64.whl", hash = "sha256:aee2512827ceb6d7f517c8b85aa5d3923afe8fc7a57d028cffcd522f1c6fd082"},
-    {file = "numpy-2.2.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3c2ec8a0f51d60f1e9c0c5ab116b7fc104b165ada3f6c58abf881cb2eb16044d"},
-    {file = "numpy-2.2.3-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:ed2cf9ed4e8ebc3b754d398cba12f24359f018b416c380f577bbae112ca52fc9"},
-    {file = "numpy-2.2.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39261798d208c3095ae4f7bc8eaeb3481ea8c6e03dc48028057d3cbdbdb8937e"},
-    {file = "numpy-2.2.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:783145835458e60fa97afac25d511d00a1eca94d4a8f3ace9fe2043003c678e4"},
-    {file = "numpy-2.2.3.tar.gz", hash = "sha256:dbdc15f0c81611925f382dfa97b3bd0bc2c1ce19d4fe50482cb0ddc12ba30020"},
-]
-
-[[package]]
-name = "outcome"
-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"},
-]
-
-[package.dependencies]
-attrs = ">=19.2.0"
-
-[[package]]
-name = "packaging"
-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"},
-]
-
-[[package]]
-name = "pandas"
-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"},
-    {file = "pandas-2.2.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d9c45366def9a3dd85a6454c0e7908f2b3b8e9c138f5dc38fed7ce720d8453ed"},
-    {file = "pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57"},
-    {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b8661b0238a69d7aafe156b7fa86c44b881387509653fdf857bebc5e4008ad42"},
-    {file = "pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f"},
-    {file = "pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645"},
-    {file = "pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039"},
-    {file = "pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd"},
-    {file = "pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698"},
-    {file = "pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc"},
-    {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3"},
-    {file = "pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32"},
-    {file = "pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5"},
-    {file = "pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9"},
-    {file = "pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4"},
-    {file = "pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3"},
-    {file = "pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319"},
-    {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8"},
-    {file = "pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a"},
-    {file = "pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13"},
-    {file = "pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015"},
-    {file = "pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28"},
-    {file = "pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0"},
-    {file = "pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24"},
-    {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659"},
-    {file = "pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb"},
-    {file = "pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d"},
-    {file = "pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468"},
-    {file = "pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18"},
-    {file = "pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2"},
-    {file = "pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4"},
-    {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d"},
-    {file = "pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a"},
-    {file = "pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39"},
-    {file = "pandas-2.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5dbca4c1acd72e8eeef4753eeca07de9b1db4f398669d5994086f788a5d7cc30"},
-    {file = "pandas-2.2.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8cd6d7cc958a3910f934ea8dbdf17b2364827bb4dafc38ce6eef6bb3d65ff09c"},
-    {file = "pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c"},
-    {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31d0ced62d4ea3e231a9f228366919a5ea0b07440d9d4dac345376fd8e1477ea"},
-    {file = "pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761"},
-    {file = "pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e"},
-    {file = "pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667"},
-]
-
-[package.dependencies]
-numpy = [
-    {version = ">=1.22.4", markers = "python_version < \"3.11\""},
-    {version = ">=1.23.2", markers = "python_version == \"3.11\""},
-    {version = ">=1.26.0", markers = "python_version >= \"3.12\""},
-]
-python-dateutil = ">=2.8.2"
-pytz = ">=2020.1"
-tzdata = ">=2022.7"
-
-[package.extras]
-all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"]
-aws = ["s3fs (>=2022.11.0)"]
-clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"]
-compression = ["zstandard (>=0.19.0)"]
-computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"]
-consortium-standard = ["dataframe-api-compat (>=0.1.7)"]
-excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"]
-feather = ["pyarrow (>=10.0.1)"]
-fss = ["fsspec (>=2022.11.0)"]
-gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"]
-hdf5 = ["tables (>=3.8.0)"]
-html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"]
-mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"]
-output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"]
-parquet = ["pyarrow (>=10.0.1)"]
-performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"]
-plot = ["matplotlib (>=3.6.3)"]
-postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"]
-pyarrow = ["pyarrow (>=10.0.1)"]
-spss = ["pyreadstat (>=1.2.0)"]
-sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"]
-test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
-xml = ["lxml (>=4.9.2)"]
-
-[[package]]
-name = "pillow"
-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"},
-    {file = "pillow-11.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a07dba04c5e22824816b2615ad7a7484432d7f540e6fa86af60d2de57b0fcee2"},
-    {file = "pillow-11.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e267b0ed063341f3e60acd25c05200df4193e15a4a5807075cd71225a2386e26"},
-    {file = "pillow-11.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bd165131fd51697e22421d0e467997ad31621b74bfc0b75956608cb2906dda07"},
-    {file = "pillow-11.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:abc56501c3fd148d60659aae0af6ddc149660469082859fa7b066a298bde9482"},
-    {file = "pillow-11.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:54ce1c9a16a9561b6d6d8cb30089ab1e5eb66918cb47d457bd996ef34182922e"},
-    {file = "pillow-11.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73ddde795ee9b06257dac5ad42fcb07f3b9b813f8c1f7f870f402f4dc54b5269"},
-    {file = "pillow-11.1.0-cp310-cp310-win32.whl", hash = "sha256:3a5fe20a7b66e8135d7fd617b13272626a28278d0e578c98720d9ba4b2439d49"},
-    {file = "pillow-11.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:b6123aa4a59d75f06e9dd3dac5bf8bc9aa383121bb3dd9a7a612e05eabc9961a"},
-    {file = "pillow-11.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:a76da0a31da6fcae4210aa94fd779c65c75786bc9af06289cd1c184451ef7a65"},
-    {file = "pillow-11.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457"},
-    {file = "pillow-11.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35"},
-    {file = "pillow-11.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2"},
-    {file = "pillow-11.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f189805c8be5ca5add39e6f899e6ce2ed824e65fb45f3c28cb2841911da19070"},
-    {file = "pillow-11.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:dd0052e9db3474df30433f83a71b9b23bd9e4ef1de13d92df21a52c0303b8ab6"},
-    {file = "pillow-11.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:837060a8599b8f5d402e97197d4924f05a2e0d68756998345c829c33186217b1"},
-    {file = "pillow-11.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:aa8dd43daa836b9a8128dbe7d923423e5ad86f50a7a14dc688194b7be5c0dea2"},
-    {file = "pillow-11.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96"},
-    {file = "pillow-11.1.0-cp311-cp311-win32.whl", hash = "sha256:c12fc111ef090845de2bb15009372175d76ac99969bdf31e2ce9b42e4b8cd88f"},
-    {file = "pillow-11.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761"},
-    {file = "pillow-11.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:f7955ecf5609dee9442cbface754f2c6e541d9e6eda87fad7f7a989b0bdb9d71"},
-    {file = "pillow-11.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a"},
-    {file = "pillow-11.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b"},
-    {file = "pillow-11.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3"},
-    {file = "pillow-11.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a"},
-    {file = "pillow-11.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1"},
-    {file = "pillow-11.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f"},
-    {file = "pillow-11.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91"},
-    {file = "pillow-11.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c"},
-    {file = "pillow-11.1.0-cp312-cp312-win32.whl", hash = "sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6"},
-    {file = "pillow-11.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf"},
-    {file = "pillow-11.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5"},
-    {file = "pillow-11.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc"},
-    {file = "pillow-11.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0"},
-    {file = "pillow-11.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1"},
-    {file = "pillow-11.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec"},
-    {file = "pillow-11.1.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5"},
-    {file = "pillow-11.1.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114"},
-    {file = "pillow-11.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352"},
-    {file = "pillow-11.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3"},
-    {file = "pillow-11.1.0-cp313-cp313-win32.whl", hash = "sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9"},
-    {file = "pillow-11.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c"},
-    {file = "pillow-11.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65"},
-    {file = "pillow-11.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861"},
-    {file = "pillow-11.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081"},
-    {file = "pillow-11.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c"},
-    {file = "pillow-11.1.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547"},
-    {file = "pillow-11.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab"},
-    {file = "pillow-11.1.0-cp313-cp313t-win32.whl", hash = "sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9"},
-    {file = "pillow-11.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe"},
-    {file = "pillow-11.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756"},
-    {file = "pillow-11.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:bf902d7413c82a1bfa08b06a070876132a5ae6b2388e2712aab3a7cbc02205c6"},
-    {file = "pillow-11.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c1eec9d950b6fe688edee07138993e54ee4ae634c51443cfb7c1e7613322718e"},
-    {file = "pillow-11.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e275ee4cb11c262bd108ab2081f750db2a1c0b8c12c1897f27b160c8bd57bbc"},
-    {file = "pillow-11.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4db853948ce4e718f2fc775b75c37ba2efb6aaea41a1a5fc57f0af59eee774b2"},
-    {file = "pillow-11.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:ab8a209b8485d3db694fa97a896d96dd6533d63c22829043fd9de627060beade"},
-    {file = "pillow-11.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:54251ef02a2309b5eec99d151ebf5c9904b77976c8abdcbce7891ed22df53884"},
-    {file = "pillow-11.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5bb94705aea800051a743aa4874bb1397d4695fb0583ba5e425ee0328757f196"},
-    {file = "pillow-11.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89dbdb3e6e9594d512780a5a1c42801879628b38e3efc7038094430844e271d8"},
-    {file = "pillow-11.1.0-cp39-cp39-win32.whl", hash = "sha256:e5449ca63da169a2e6068dd0e2fcc8d91f9558aba89ff6d02121ca8ab11e79e5"},
-    {file = "pillow-11.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:3362c6ca227e65c54bf71a5f88b3d4565ff1bcbc63ae72c34b07bbb1cc59a43f"},
-    {file = "pillow-11.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:b20be51b37a75cc54c2c55def3fa2c65bb94ba859dde241cd0a4fd302de5ae0a"},
-    {file = "pillow-11.1.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8c730dc3a83e5ac137fbc92dfcfe1511ce3b2b5d7578315b63dbbb76f7f51d90"},
-    {file = "pillow-11.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d33d2fae0e8b170b6a6c57400e077412240f6f5bb2a342cf1ee512a787942bb"},
-    {file = "pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8d65b38173085f24bc07f8b6c505cbb7418009fa1a1fcb111b1f4961814a442"},
-    {file = "pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:015c6e863faa4779251436db398ae75051469f7c903b043a48f078e437656f83"},
-    {file = "pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d44ff19eea13ae4acdaaab0179fa68c0c6f2f45d66a4d8ec1eda7d6cecbcc15f"},
-    {file = "pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d3d8da4a631471dfaf94c10c85f5277b1f8e42ac42bade1ac67da4b4a7359b73"},
-    {file = "pillow-11.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0"},
-    {file = "pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20"},
-]
-
-[package.extras]
-docs = ["furo", "olefile", "sphinx (>=8.1)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"]
-fpx = ["olefile"]
-mic = ["olefile"]
-tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "trove-classifiers (>=2024.10.12)"]
-typing = ["typing-extensions"]
-xmp = ["defusedxml"]
-
-[[package]]
-name = "platformdirs"
-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"},
-]
-
-[package.extras]
-docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"]
-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.50.0"
-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.50.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:f36d754a6c5bd9bf7f14e8f57a2aea6fd08f39ca4c8476481b9c83e299531148"},
-    {file = "playwright-1.50.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:40f274384591dfd27f2b014596250b2250c843ed1f7f4ef5d2960ecb91b4961e"},
-    {file = "playwright-1.50.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:9922ef9bcd316995f01e220acffd2d37a463b4ad10fd73e388add03841dfa230"},
-    {file = "playwright-1.50.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:8fc628c492d12b13d1f347137b2ac6c04f98197ff0985ef0403a9a9ee0d39131"},
-    {file = "playwright-1.50.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcff35f72db2689a79007aee78f1b0621a22e6e3d6c1f58aaa9ac805bf4497c"},
-    {file = "playwright-1.50.0-py3-none-win32.whl", hash = "sha256:3b906f4d351260016a8c5cc1e003bb341651ae682f62213b50168ed581c7558a"},
-    {file = "playwright-1.50.0-py3-none-win_amd64.whl", hash = "sha256:1859423da82de631704d5e3d88602d755462b0906824c1debe140979397d2e8d"},
-]
-
-[package.dependencies]
-greenlet = ">=3.1.1,<4.0.0"
-pyee = ">=12,<13"
-
-[[package]]
-name = "plotly"
-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"},
-]
-
-[package.dependencies]
-packaging = "*"
-tenacity = ">=6.2.0"
-
-[[package]]
-name = "pluggy"
-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"},
-]
-
-[package.extras]
-dev = ["pre-commit", "tox"]
-testing = ["pytest", "pytest-benchmark"]
-
-[[package]]
-name = "pre-commit"
-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"},
-]
-
-[package.dependencies]
-cfgv = ">=2.0.0"
-identify = ">=1.0.0"
-nodeenv = ">=0.11.1"
-pyyaml = ">=5.1"
-virtualenv = ">=20.10.0"
-
-[[package]]
-name = "psutil"
-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"},
-    {file = "psutil-6.1.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:8df0178ba8a9e5bc84fed9cfa61d54601b371fbec5c8eebad27575f1e105c0d4"},
-    {file = "psutil-6.1.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:1924e659d6c19c647e763e78670a05dbb7feaf44a0e9c94bf9e14dfc6ba50468"},
-    {file = "psutil-6.1.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:018aeae2af92d943fdf1da6b58665124897cfc94faa2ca92098838f83e1b1bca"},
-    {file = "psutil-6.1.1-cp27-none-win32.whl", hash = "sha256:6d4281f5bbca041e2292be3380ec56a9413b790579b8e593b1784499d0005dac"},
-    {file = "psutil-6.1.1-cp27-none-win_amd64.whl", hash = "sha256:c777eb75bb33c47377c9af68f30e9f11bc78e0f07fbf907be4a5d70b2fe5f030"},
-    {file = "psutil-6.1.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8"},
-    {file = "psutil-6.1.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377"},
-    {file = "psutil-6.1.1-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003"},
-    {file = "psutil-6.1.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160"},
-    {file = "psutil-6.1.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3"},
-    {file = "psutil-6.1.1-cp36-cp36m-win32.whl", hash = "sha256:384636b1a64b47814437d1173be1427a7c83681b17a450bfc309a1953e329603"},
-    {file = "psutil-6.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8be07491f6ebe1a693f17d4f11e69d0dc1811fa082736500f649f79df7735303"},
-    {file = "psutil-6.1.1-cp37-abi3-win32.whl", hash = "sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53"},
-    {file = "psutil-6.1.1-cp37-abi3-win_amd64.whl", hash = "sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649"},
-    {file = "psutil-6.1.1.tar.gz", hash = "sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5"},
-]
-
-[package.extras]
-dev = ["abi3audit", "black", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest-cov", "requests", "rstcheck", "ruff", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "vulture", "wheel"]
-test = ["pytest", "pytest-xdist", "setuptools"]
-
-[[package]]
-name = "py-cpuinfo"
-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"},
-]
-
-[[package]]
-name = "pycparser"
-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 = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" and platform_python_implementation != \"PyPy\" or python_version >= \"3.12\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" and platform_python_implementation != \"PyPy\"", dev = "python_version <= \"3.11\" or python_version >= \"3.12\""}
-
-[[package]]
-name = "pydantic"
-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.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"},
-    {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"},
-]
-
-[package.dependencies]
-annotated-types = ">=0.6.0"
-pydantic-core = "2.27.2"
-typing-extensions = ">=4.12.2"
-
-[package.extras]
-email = ["email-validator (>=2.0.0)"]
-timezone = ["tzdata"]
-
-[[package]]
-name = "pydantic-core"
-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"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"},
-    {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"},
-    {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"},
-    {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"},
-    {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"},
-    {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"},
-    {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"},
-    {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"},
-    {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"},
-    {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"},
-    {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"},
-    {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"},
-    {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"},
-    {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"},
-    {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"},
-    {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"},
-    {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"},
-    {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"},
-    {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"},
-    {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"},
-    {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"},
-    {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"},
-    {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"},
-    {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"},
-    {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"},
-    {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"},
-]
-
-[package.dependencies]
-typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
-
-[[package]]
-name = "pyee"
-version = "12.1.1"
-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.1.1-py3-none-any.whl", hash = "sha256:18a19c650556bb6b32b406d7f017c8f513aceed1ef7ca618fb65de7bd2d347ef"},
-    {file = "pyee-12.1.1.tar.gz", hash = "sha256:bbc33c09e2ff827f74191e3e5bbc6be7da02f627b7ec30d86f5ce1a6fb2424a3"},
-]
-
-[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.19.1"
-description = "Pygments is a syntax highlighting package written in Python."
-optional = false
-python-versions = ">=3.8"
-groups = ["main", "dev"]
-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"},
-]
-
-[package.extras]
-windows-terminal = ["colorama (>=0.4.6)"]
-
-[[package]]
-name = "pyproject-hooks"
-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"},
-]
-
-[[package]]
-name = "pyright"
-version = "1.1.394"
-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.394-py3-none-any.whl", hash = "sha256:5f74cce0a795a295fb768759bbeeec62561215dea657edcaab48a932b031ddbb"},
-    {file = "pyright-1.1.394.tar.gz", hash = "sha256:56f2a3ab88c5214a451eb71d8f2792b7700434f841ea219119ade7f42ca93608"},
-]
-
-[package.dependencies]
-nodeenv = ">=1.6.0"
-typing-extensions = ">=4.1"
-
-[package.extras]
-all = ["nodejs-wheel-binaries", "twine (>=3.4.1)"]
-dev = ["twine (>=3.4.1)"]
-nodejs = ["nodejs-wheel-binaries"]
-
-[[package]]
-name = "pysocks"
-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"},
-    {file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"},
-]
-
-[[package]]
-name = "pytest"
-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"},
-]
-
-[package.dependencies]
-colorama = {version = "*", markers = "sys_platform == \"win32\""}
-exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
-iniconfig = "*"
-packaging = "*"
-pluggy = ">=1.5,<2"
-tomli = {version = ">=1", markers = "python_version < \"3.11\""}
-
-[package.extras]
-dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
-
-[[package]]
-name = "pytest-asyncio"
-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.3-py3-none-any.whl", hash = "sha256:9e89518e0f9bd08928f97a3482fdc4e244df17529460bc038291ccaf8f85c7c3"},
-    {file = "pytest_asyncio-0.25.3.tar.gz", hash = "sha256:fc1da2cf9f125ada7e710b4ddad05518d4cee187ae9412e9ac9271003497f07a"},
-]
-
-[package.dependencies]
-pytest = ">=8.2,<9"
-
-[package.extras]
-docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)"]
-testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"]
-
-[[package]]
-name = "pytest-base-url"
-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"},
-]
-
-[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 = "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"},
-]
-
-[package.dependencies]
-py-cpuinfo = "*"
-pytest = ">=8.1"
-
-[package.extras]
-aspect = ["aspectlib"]
-elasticsearch = ["elasticsearch"]
-histogram = ["pygal", "pygaljs", "setuptools"]
-
-[[package]]
-name = "pytest-codspeed"
-version = "3.2.0"
-description = "Pytest plugin to create CodSpeed benchmarks"
-optional = false
-python-versions = ">=3.9"
-groups = ["dev"]
-markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
-files = [
-    {file = "pytest_codspeed-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c5165774424c7ab8db7e7acdb539763a0e5657996effefdf0664d7fd95158d34"},
-    {file = "pytest_codspeed-3.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bd55f92d772592c04a55209950c50880413ae46876e66bd349ef157075ca26c"},
-    {file = "pytest_codspeed-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf6f56067538f4892baa8d7ab5ef4e45bb59033be1ef18759a2c7fc55b32035"},
-    {file = "pytest_codspeed-3.2.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:39a687b05c3d145642061b45ea78e47e12f13ce510104d1a2cda00eee0e36f58"},
-    {file = "pytest_codspeed-3.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:46a1afaaa1ac4c2ca5b0700d31ac46d80a27612961d031067d73c6ccbd8d3c2b"},
-    {file = "pytest_codspeed-3.2.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c48ce3af3dfa78413ed3d69d1924043aa1519048dbff46edccf8f35a25dab3c2"},
-    {file = "pytest_codspeed-3.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:66692506d33453df48b36a84703448cb8b22953eea51f03fbb2eb758dc2bdc4f"},
-    {file = "pytest_codspeed-3.2.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:479774f80d0bdfafa16112700df4dbd31bf2a6757fac74795fd79c0a7b3c389b"},
-    {file = "pytest_codspeed-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:109f9f4dd1088019c3b3f887d003b7d65f98a7736ca1d457884f5aa293e8e81c"},
-    {file = "pytest_codspeed-3.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2f69a03b52c9bb041aec1b8ee54b7b6c37a6d0a948786effa4c71157765b6da"},
-    {file = "pytest_codspeed-3.2.0-py3-none-any.whl", hash = "sha256:54b5c2e986d6a28e7b0af11d610ea57bd5531cec8326abe486f1b55b09d91c39"},
-    {file = "pytest_codspeed-3.2.0.tar.gz", hash = "sha256:f9d1b1a3b2c69cdc0490a1e8b1ced44bffbd0e8e21d81a7160cfdd923f6e8155"},
-]
-
-[package.dependencies]
-cffi = ">=1.17.1"
-pytest = ">=3.8"
-rich = ">=13.8.1"
-
-[package.extras]
-compat = ["pytest-benchmark (>=5.0.0,<5.1.0)", "pytest-xdist (>=3.6.1,<3.7.0)"]
-lint = ["mypy (>=1.11.2,<1.12.0)", "ruff (>=0.6.5,<0.7.0)"]
-test = ["pytest (>=7.0,<8.0)", "pytest-cov (>=4.0.0,<4.1.0)"]
-
-[[package]]
-name = "pytest-cov"
-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"},
-]
-
-[package.dependencies]
-coverage = {version = ">=7.5", extras = ["toml"]}
-pytest = ">=4.6"
-
-[package.extras]
-testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"]
-
-[[package]]
-name = "pytest-mock"
-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"},
-]
-
-[package.dependencies]
-pytest = ">=6.2.5"
-
-[package.extras]
-dev = ["pre-commit", "pytest-asyncio", "tox"]
-
-[[package]]
-name = "pytest-playwright"
-version = "0.7.0"
-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.7.0-py3-none-any.whl", hash = "sha256:2516d0871fa606634bfe32afbcc0342d68da2dbff97fe3459849e9c428486da2"},
-    {file = "pytest_playwright-0.7.0.tar.gz", hash = "sha256:b3f2ea514bbead96d26376fac182f68dcd6571e7cb41680a89ff1673c05d60b6"},
-]
-
-[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"
-description = "Extensions to the standard Python datetime module"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
-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"},
-    {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"},
-]
-
-[package.dependencies]
-six = ">=1.5"
-
-[[package]]
-name = "python-engineio"
-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"},
-]
-
-[package.dependencies]
-simple-websocket = ">=0.10.0"
-
-[package.extras]
-asyncio-client = ["aiohttp (>=3.4)"]
-client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
-docs = ["sphinx"]
-
-[[package]]
-name = "python-multipart"
-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"},
-]
-
-[[package]]
-name = "python-slugify"
-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"},
-]
-
-[package.dependencies]
-text-unidecode = ">=1.3"
-
-[package.extras]
-unidecode = ["Unidecode (>=1.1.1)"]
-
-[[package]]
-name = "python-socketio"
-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"},
-]
-
-[package.dependencies]
-bidict = ">=0.21.0"
-python-engineio = ">=4.11.0"
-
-[package.extras]
-asyncio-client = ["aiohttp (>=3.4)"]
-client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
-docs = ["sphinx"]
-
-[[package]]
-name = "pytz"
-version = "2025.1"
-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-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57"},
-    {file = "pytz-2025.1.tar.gz", hash = "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e"},
-]
-
-[[package]]
-name = "pywin32-ctypes"
-version = "0.2.3"
-description = "A (partial) reimplementation of pywin32 using ctypes/cffi"
-optional = false
-python-versions = ">=3.6"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"win32\" or python_version >= \"3.12\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"win32\""
-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"},
-]
-
-[[package]]
-name = "pyyaml"
-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"},
-    {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"},
-    {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"},
-    {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"},
-    {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"},
-    {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"},
-    {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"},
-    {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"},
-    {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"},
-    {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"},
-    {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"},
-    {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"},
-    {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"},
-    {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"},
-    {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"},
-    {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"},
-    {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"},
-    {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"},
-    {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"},
-    {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"},
-    {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"},
-    {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"},
-    {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"},
-    {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"},
-    {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"},
-    {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"},
-    {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"},
-    {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"},
-    {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"},
-    {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"},
-    {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"},
-    {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"},
-    {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"},
-    {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"},
-    {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"},
-    {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"},
-    {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"},
-    {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"},
-    {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"},
-    {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"},
-    {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"},
-    {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"},
-    {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"},
-    {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"},
-    {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"},
-    {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"},
-    {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"},
-    {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"},
-    {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"},
-    {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"},
-    {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"},
-    {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"},
-]
-
-[[package]]
-name = "readme-renderer"
-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"},
-]
-
-[package.dependencies]
-docutils = ">=0.21.2"
-nh3 = ">=0.2.14"
-Pygments = ">=2.5.1"
-
-[package.extras]
-md = ["cmarkgfm (>=0.8.0)"]
-
-[[package]]
-name = "redis"
-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"},
-]
-
-[package.dependencies]
-async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""}
-
-[package.extras]
-hiredis = ["hiredis (>=3.0.0)"]
-ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==23.2.1)", "requests (>=2.31.0)"]
-
-[[package]]
-name = "reflex-hosting-cli"
-version = "0.1.35"
-description = "Reflex Hosting CLI"
-optional = false
-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.35-py3-none-any.whl", hash = "sha256:619687be27e6691cb54f6cf038e98d4d622fcf25a85bc9986f8daf52b48e6744"},
-    {file = "reflex_hosting_cli-0.1.35.tar.gz", hash = "sha256:9a5d02978b900045464a1a5581f3adc6260daaa09e8acf95fd05024cda926ae7"},
-]
-
-[package.dependencies]
-charset-normalizer = ">=3.3.2,<4.0.0"
-httpx = ">=0.25.1,<1.0"
-platformdirs = ">=3.10.0,<5.0"
-pydantic = ">=1.10.2,<3.0"
-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"
-
-[[package]]
-name = "requests"
-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"},
-]
-
-[package.dependencies]
-certifi = ">=2017.4.17"
-charset-normalizer = ">=2,<4"
-idna = ">=2.5,<4"
-urllib3 = ">=1.21.1,<3"
-
-[package.extras]
-socks = ["PySocks (>=1.5.6,!=1.5.7)"]
-use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
-
-[[package]]
-name = "requests-toolbelt"
-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"},
-]
-
-[package.dependencies]
-requests = ">=2.0.1,<3.0.0"
-
-[[package]]
-name = "rfc3986"
-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"},
-]
-
-[package.extras]
-idna2008 = ["idna"]
-
-[[package]]
-name = "rich"
-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", "dev"]
-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"},
-]
-
-[package.dependencies]
-markdown-it-py = ">=2.2.0"
-pygments = ">=2.13.0,<3.0.0"
-typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""}
-
-[package.extras]
-jupyter = ["ipywidgets (>=7.5.1,<9)"]
-
-[[package]]
-name = "ruff"
-version = "0.9.6"
-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.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba"},
-    {file = "ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504"},
-    {file = "ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83"},
-    {file = "ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc"},
-    {file = "ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b"},
-    {file = "ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e"},
-    {file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666"},
-    {file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5"},
-    {file = "ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5"},
-    {file = "ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217"},
-    {file = "ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6"},
-    {file = "ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897"},
-    {file = "ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08"},
-    {file = "ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656"},
-    {file = "ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d"},
-    {file = "ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa"},
-    {file = "ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a"},
-    {file = "ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9"},
-]
-
-[[package]]
-name = "secretstorage"
-version = "3.3.3"
-description = "Python bindings to FreeDesktop.org Secret Service API"
-optional = false
-python-versions = ">=3.6"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\" or python_version >= \"3.12\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") and sys_platform == \"linux\""
-files = [
-    {file = "SecretStorage-3.3.3-py3-none-any.whl", hash = "sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99"},
-    {file = "SecretStorage-3.3.3.tar.gz", hash = "sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77"},
-]
-
-[package.dependencies]
-cryptography = ">=2.0"
-jeepney = ">=0.6"
-
-[[package]]
-name = "selenium"
-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.1-py3-none-any.whl", hash = "sha256:4238847e45e24e4472cfcf3554427512c7aab9443396435b1623ef406fff1cc1"},
-    {file = "selenium-4.28.1.tar.gz", hash = "sha256:0072d08670d7ec32db901bd0107695a330cecac9f196e3afb3fa8163026e022a"},
-]
-
-[package.dependencies]
-certifi = ">=2021.10.8"
-trio = ">=0.17,<1.0"
-trio-websocket = ">=0.9,<1.0"
-typing_extensions = ">=4.9,<5.0"
-urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
-websocket-client = ">=1.8,<2.0"
-
-[[package]]
-name = "setuptools"
-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"},
-]
-
-[package.extras]
-check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"]
-core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
-cover = ["pytest-cov"]
-doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
-enabler = ["pytest-enabler (>=2.2)"]
-test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
-type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"]
-
-[[package]]
-name = "shellingham"
-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"},
-]
-
-[[package]]
-name = "simple-websocket"
-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"},
-]
-
-[package.dependencies]
-wsproto = "*"
-
-[package.extras]
-dev = ["flake8", "pytest", "pytest-cov", "tox"]
-docs = ["sphinx"]
-
-[[package]]
-name = "six"
-version = "1.17.0"
-description = "Python 2 and 3 compatibility utilities"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
-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"},
-    {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"},
-]
-
-[[package]]
-name = "sniffio"
-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"},
-]
-
-[[package]]
-name = "sortedcontainers"
-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"},
-]
-
-[[package]]
-name = "sqlalchemy"
-version = "2.0.38"
-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.38-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5e1d9e429028ce04f187a9f522818386c8b076723cdbe9345708384f49ebcec6"},
-    {file = "SQLAlchemy-2.0.38-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b87a90f14c68c925817423b0424381f0e16d80fc9a1a1046ef202ab25b19a444"},
-    {file = "SQLAlchemy-2.0.38-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:402c2316d95ed90d3d3c25ad0390afa52f4d2c56b348f212aa9c8d072a40eee5"},
-    {file = "SQLAlchemy-2.0.38-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6493bc0eacdbb2c0f0d260d8988e943fee06089cd239bd7f3d0c45d1657a70e2"},
-    {file = "SQLAlchemy-2.0.38-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0561832b04c6071bac3aad45b0d3bb6d2c4f46a8409f0a7a9c9fa6673b41bc03"},
-    {file = "SQLAlchemy-2.0.38-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:49aa2cdd1e88adb1617c672a09bf4ebf2f05c9448c6dbeba096a3aeeb9d4d443"},
-    {file = "SQLAlchemy-2.0.38-cp310-cp310-win32.whl", hash = "sha256:64aa8934200e222f72fcfd82ee71c0130a9c07d5725af6fe6e919017d095b297"},
-    {file = "SQLAlchemy-2.0.38-cp310-cp310-win_amd64.whl", hash = "sha256:c57b8e0841f3fce7b703530ed70c7c36269c6d180ea2e02e36b34cb7288c50c7"},
-    {file = "SQLAlchemy-2.0.38-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bf89e0e4a30714b357f5d46b6f20e0099d38b30d45fa68ea48589faf5f12f62d"},
-    {file = "SQLAlchemy-2.0.38-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8455aa60da49cb112df62b4721bd8ad3654a3a02b9452c783e651637a1f21fa2"},
-    {file = "SQLAlchemy-2.0.38-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f53c0d6a859b2db58332e0e6a921582a02c1677cc93d4cbb36fdf49709b327b2"},
-    {file = "SQLAlchemy-2.0.38-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3c4817dff8cef5697f5afe5fec6bc1783994d55a68391be24cb7d80d2dbc3a6"},
-    {file = "SQLAlchemy-2.0.38-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9cea5b756173bb86e2235f2f871b406a9b9d722417ae31e5391ccaef5348f2c"},
-    {file = "SQLAlchemy-2.0.38-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:40e9cdbd18c1f84631312b64993f7d755d85a3930252f6276a77432a2b25a2f3"},
-    {file = "SQLAlchemy-2.0.38-cp311-cp311-win32.whl", hash = "sha256:cb39ed598aaf102251483f3e4675c5dd6b289c8142210ef76ba24aae0a8f8aba"},
-    {file = "SQLAlchemy-2.0.38-cp311-cp311-win_amd64.whl", hash = "sha256:f9d57f1b3061b3e21476b0ad5f0397b112b94ace21d1f439f2db472e568178ae"},
-    {file = "SQLAlchemy-2.0.38-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12d5b06a1f3aeccf295a5843c86835033797fea292c60e72b07bcb5d820e6dd3"},
-    {file = "SQLAlchemy-2.0.38-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e036549ad14f2b414c725349cce0772ea34a7ab008e9cd67f9084e4f371d1f32"},
-    {file = "SQLAlchemy-2.0.38-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee3bee874cb1fadee2ff2b79fc9fc808aa638670f28b2145074538d4a6a5028e"},
-    {file = "SQLAlchemy-2.0.38-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e185ea07a99ce8b8edfc788c586c538c4b1351007e614ceb708fd01b095ef33e"},
-    {file = "SQLAlchemy-2.0.38-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b79ee64d01d05a5476d5cceb3c27b5535e6bb84ee0f872ba60d9a8cd4d0e6579"},
-    {file = "SQLAlchemy-2.0.38-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afd776cf1ebfc7f9aa42a09cf19feadb40a26366802d86c1fba080d8e5e74bdd"},
-    {file = "SQLAlchemy-2.0.38-cp312-cp312-win32.whl", hash = "sha256:a5645cd45f56895cfe3ca3459aed9ff2d3f9aaa29ff7edf557fa7a23515a3725"},
-    {file = "SQLAlchemy-2.0.38-cp312-cp312-win_amd64.whl", hash = "sha256:1052723e6cd95312f6a6eff9a279fd41bbae67633415373fdac3c430eca3425d"},
-    {file = "SQLAlchemy-2.0.38-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ecef029b69843b82048c5b347d8e6049356aa24ed644006c9a9d7098c3bd3bfd"},
-    {file = "SQLAlchemy-2.0.38-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c8bcad7fc12f0cc5896d8e10fdf703c45bd487294a986903fe032c72201596b"},
-    {file = "SQLAlchemy-2.0.38-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a0ef3f98175d77180ffdc623d38e9f1736e8d86b6ba70bff182a7e68bed7727"},
-    {file = "SQLAlchemy-2.0.38-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b0ac78898c50e2574e9f938d2e5caa8fe187d7a5b69b65faa1ea4648925b096"},
-    {file = "SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9eb4fa13c8c7a2404b6a8e3772c17a55b1ba18bc711e25e4d6c0c9f5f541b02a"},
-    {file = "SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5dba1cdb8f319084f5b00d41207b2079822aa8d6a4667c0f369fce85e34b0c86"},
-    {file = "SQLAlchemy-2.0.38-cp313-cp313-win32.whl", hash = "sha256:eae27ad7580529a427cfdd52c87abb2dfb15ce2b7a3e0fc29fbb63e2ed6f8120"},
-    {file = "SQLAlchemy-2.0.38-cp313-cp313-win_amd64.whl", hash = "sha256:b335a7c958bc945e10c522c069cd6e5804f4ff20f9a744dd38e748eb602cbbda"},
-    {file = "SQLAlchemy-2.0.38-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:40310db77a55512a18827488e592965d3dec6a3f1e3d8af3f8243134029daca3"},
-    {file = "SQLAlchemy-2.0.38-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d3043375dd5bbcb2282894cbb12e6c559654c67b5fffb462fda815a55bf93f7"},
-    {file = "SQLAlchemy-2.0.38-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70065dfabf023b155a9c2a18f573e47e6ca709b9e8619b2e04c54d5bcf193178"},
-    {file = "SQLAlchemy-2.0.38-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:c058b84c3b24812c859300f3b5abf300daa34df20d4d4f42e9652a4d1c48c8a4"},
-    {file = "SQLAlchemy-2.0.38-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0398361acebb42975deb747a824b5188817d32b5c8f8aba767d51ad0cc7bb08d"},
-    {file = "SQLAlchemy-2.0.38-cp37-cp37m-win32.whl", hash = "sha256:a2bc4e49e8329f3283d99840c136ff2cd1a29e49b5624a46a290f04dff48e079"},
-    {file = "SQLAlchemy-2.0.38-cp37-cp37m-win_amd64.whl", hash = "sha256:9cd136184dd5f58892f24001cdce986f5d7e96059d004118d5410671579834a4"},
-    {file = "SQLAlchemy-2.0.38-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:665255e7aae5f38237b3a6eae49d2358d83a59f39ac21036413fab5d1e810578"},
-    {file = "SQLAlchemy-2.0.38-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:92f99f2623ff16bd4aaf786ccde759c1f676d39c7bf2855eb0b540e1ac4530c8"},
-    {file = "SQLAlchemy-2.0.38-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa498d1392216fae47eaf10c593e06c34476ced9549657fca713d0d1ba5f7248"},
-    {file = "SQLAlchemy-2.0.38-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9afbc3909d0274d6ac8ec891e30210563b2c8bdd52ebbda14146354e7a69373"},
-    {file = "SQLAlchemy-2.0.38-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:57dd41ba32430cbcc812041d4de8d2ca4651aeefad2626921ae2a23deb8cd6ff"},
-    {file = "SQLAlchemy-2.0.38-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3e35d5565b35b66905b79ca4ae85840a8d40d31e0b3e2990f2e7692071b179ca"},
-    {file = "SQLAlchemy-2.0.38-cp38-cp38-win32.whl", hash = "sha256:f0d3de936b192980209d7b5149e3c98977c3810d401482d05fb6d668d53c1c63"},
-    {file = "SQLAlchemy-2.0.38-cp38-cp38-win_amd64.whl", hash = "sha256:3868acb639c136d98107c9096303d2d8e5da2880f7706f9f8c06a7f961961149"},
-    {file = "SQLAlchemy-2.0.38-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07258341402a718f166618470cde0c34e4cec85a39767dce4e24f61ba5e667ea"},
-    {file = "SQLAlchemy-2.0.38-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a826f21848632add58bef4f755a33d45105d25656a0c849f2dc2df1c71f6f50"},
-    {file = "SQLAlchemy-2.0.38-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:386b7d136919bb66ced64d2228b92d66140de5fefb3c7df6bd79069a269a7b06"},
-    {file = "SQLAlchemy-2.0.38-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f2951dc4b4f990a4b394d6b382accb33141d4d3bd3ef4e2b27287135d6bdd68"},
-    {file = "SQLAlchemy-2.0.38-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8bf312ed8ac096d674c6aa9131b249093c1b37c35db6a967daa4c84746bc1bc9"},
-    {file = "SQLAlchemy-2.0.38-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6db316d6e340f862ec059dc12e395d71f39746a20503b124edc255973977b728"},
-    {file = "SQLAlchemy-2.0.38-cp39-cp39-win32.whl", hash = "sha256:c09a6ea87658695e527104cf857c70f79f14e9484605e205217aae0ec27b45fc"},
-    {file = "SQLAlchemy-2.0.38-cp39-cp39-win_amd64.whl", hash = "sha256:12f5c9ed53334c3ce719155424dc5407aaa4f6cadeb09c5b627e06abb93933a1"},
-    {file = "SQLAlchemy-2.0.38-py3-none-any.whl", hash = "sha256:63178c675d4c80def39f1febd625a6333f44c0ba269edd8a468b156394b27753"},
-    {file = "sqlalchemy-2.0.38.tar.gz", hash = "sha256:e5a4d82bdb4bf1ac1285a68eab02d253ab73355d9f0fe725a97e1e0fa689decb"},
-]
-
-[package.dependencies]
-greenlet = {version = "!=0.4.17", markers = "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\")"}
-typing-extensions = ">=4.6.0"
-
-[package.extras]
-aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"]
-aioodbc = ["aioodbc", "greenlet (!=0.4.17)"]
-aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"]
-asyncio = ["greenlet (!=0.4.17)"]
-asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"]
-mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5,!=1.1.10)"]
-mssql = ["pyodbc"]
-mssql-pymssql = ["pymssql"]
-mssql-pyodbc = ["pyodbc"]
-mypy = ["mypy (>=0.910)"]
-mysql = ["mysqlclient (>=1.4.0)"]
-mysql-connector = ["mysql-connector-python"]
-oracle = ["cx_oracle (>=8)"]
-oracle-oracledb = ["oracledb (>=1.0.1)"]
-postgresql = ["psycopg2 (>=2.7)"]
-postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"]
-postgresql-pg8000 = ["pg8000 (>=1.29.1)"]
-postgresql-psycopg = ["psycopg (>=3.0.7)"]
-postgresql-psycopg2binary = ["psycopg2-binary"]
-postgresql-psycopg2cffi = ["psycopg2cffi"]
-postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"]
-pymysql = ["pymysql"]
-sqlcipher = ["sqlcipher3_binary"]
-
-[[package]]
-name = "sqlmodel"
-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"},
-]
-
-[package.dependencies]
-pydantic = ">=1.10.13,<3.0.0"
-SQLAlchemy = ">=2.0.14,<2.1.0"
-
-[[package]]
-name = "starlette"
-version = "0.45.3"
-description = "The little ASGI library that shines."
-optional = false
-python-versions = ">=3.9"
-groups = ["main"]
-markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
-files = [
-    {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.6.2,<5"
-
-[package.extras]
-full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"]
-
-[[package]]
-name = "starlette-admin"
-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"},
-]
-
-[package.dependencies]
-jinja2 = ">=3,<4"
-python-multipart = "*"
-starlette = "*"
-
-[package.extras]
-cov = ["coverage[toml] (>=7.0.0,<7.4.0)"]
-dev = ["pre-commit (>=2.20.0,<4.0.0)", "uvicorn (>=0.20.0,<0.31.0)"]
-doc = ["mkdocs (>=1.4.2,<2.0.0)", "mkdocs-material (>=9.0.0,<10.0.0)", "mkdocs-static-i18n (>=1.2.3,<1.3)", "mkdocstrings[python] (>=0.19.0,<0.26.0)"]
-i18n = ["babel (>=2.13.0)"]
-test = ["aiomysql (>=0.1.1,<0.3.0)", "aiosqlite (>=0.17.0,<0.21.0)", "arrow (>=1.2.3,<1.4.0)", "asyncpg (>=0.27.0,<0.30.0)", "backports-zoneinfo", "black (==24.4.2)", "colour (>=0.1.5,<0.2.0)", "fasteners (==0.19)", "httpx (>=0.23.3,<0.27.0)", "itsdangerous (>=2.2.0,<2.3.0)", "mongoengine (>=0.25.0,<0.29.0)", "mypy (==1.10.0)", "odmantic (>=0.9.0,<0.10.0)", "passlib (>=1.7.4,<1.8.0)", "phonenumbers (>=8.13.3,<8.14.0)", "pillow (>=9.4.0,<9.6.0)", "psycopg2-binary (>=2.9.5,<3.0.0)", "pydantic[email] (>=1.10.2,<2.8.0)", "pymysql[rsa] (>=1.0.2,<1.2.0)", "pytest (>=7.2.0,<7.5.0)", "pytest-asyncio (>=0.20.2,<0.24.0)", "ruff (==0.4.8)", "sqlalchemy-file (>=0.5.0,<0.7.0)", "sqlalchemy-utils (>=0.40.0,<0.42.0)", "sqlmodel (>=0.0.11,<0.15.0)", "tinydb (>=4.7.0,<4.9.0)"]
-
-[[package]]
-name = "tabulate"
-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"},
-]
-
-[package.extras]
-widechars = ["wcwidth"]
-
-[[package]]
-name = "tenacity"
-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"},
-]
-
-[package.extras]
-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 = "*"
-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"},
-]
-
-[[package]]
-name = "toml"
-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"},
-]
-
-[[package]]
-name = "tomli"
-version = "2.2.1"
-description = "A lil' TOML parser"
-optional = false
-python-versions = ">=3.8"
-groups = ["main", "dev"]
-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"},
-    {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
-    {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
-    {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
-    {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
-    {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
-    {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
-    {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
-    {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
-    {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
-    {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
-    {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
-    {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
-    {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
-    {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
-    {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
-    {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
-    {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
-    {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
-    {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
-    {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
-    {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
-    {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
-    {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
-    {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
-    {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
-    {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
-    {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
-    {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
-    {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
-    {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
-]
-markers = {main = "python_version < \"3.11\"", dev = "python_full_version <= \"3.11.0a6\""}
-
-[[package]]
-name = "tomlkit"
-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"},
-]
-
-[[package]]
-name = "trio"
-version = "0.29.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.29.0-py3-none-any.whl", hash = "sha256:d8c463f1a9cc776ff63e331aba44c125f423a5a13c684307e828d930e625ba66"},
-    {file = "trio-0.29.0.tar.gz", hash = "sha256:ea0d3967159fc130acb6939a0be0e558e364fee26b5deeecc893a6b08c361bdf"},
-]
-
-[package.dependencies]
-attrs = ">=23.2.0"
-cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""}
-exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
-idna = "*"
-outcome = "*"
-sniffio = ">=1.3.0"
-sortedcontainers = "*"
-
-[[package]]
-name = "trio-websocket"
-version = "0.12.1"
-description = "WebSocket library for Trio"
-optional = false
-python-versions = ">=3.8"
-groups = ["dev"]
-markers = "python_version <= \"3.11\" or python_version >= \"3.12\""
-files = [
-    {file = "trio_websocket-0.12.1-py3-none-any.whl", hash = "sha256:608ec746bb287e5d5a66baf483e41194193c5cf05ffaad6240e7d1fcd80d1e6f"},
-    {file = "trio_websocket-0.12.1.tar.gz", hash = "sha256:d55ccd4d3eae27c494f3fdae14823317839bdcb8214d1173eacc4d42c69fc91b"},
-]
-
-[package.dependencies]
-exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
-outcome = ">=1.2.0"
-trio = ">=0.11"
-wsproto = ">=0.14"
-
-[[package]]
-name = "twine"
-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"},
-]
-
-[package.dependencies]
-id = "*"
-keyring = {version = ">=15.1", markers = "platform_machine != \"ppc64le\" and platform_machine != \"s390x\""}
-packaging = ">=24.0"
-readme-renderer = ">=35.0"
-requests = ">=2.20"
-requests-toolbelt = ">=0.8.0,<0.9.0 || >0.9.0"
-rfc3986 = ">=1.4.0"
-rich = ">=12.0.0"
-urllib3 = ">=1.26.0"
-
-[package.extras]
-keyring = ["keyring (>=15.1)"]
-
-[[package]]
-name = "typer"
-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"},
-]
-
-[package.dependencies]
-click = ">=8.0.0"
-rich = ">=10.11.0"
-shellingham = ">=1.3.0"
-typing-extensions = ">=3.7.4.3"
-
-[[package]]
-name = "typing-extensions"
-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"},
-]
-
-[[package]]
-name = "tzdata"
-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"},
-]
-
-[[package]]
-name = "urllib3"
-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"},
-]
-
-[package.dependencies]
-pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
-
-[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
-h2 = ["h2 (>=4,<5)"]
-socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
-zstd = ["zstandard (>=0.18.0)"]
-
-[[package]]
-name = "uvicorn"
-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"},
-]
-
-[package.dependencies]
-click = ">=7.0"
-h11 = ">=0.8"
-typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""}
-
-[package.extras]
-standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
-
-[[package]]
-name = "virtualenv"
-version = "20.29.2"
-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.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a"},
-    {file = "virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728"},
-]
-
-[package.dependencies]
-distlib = ">=0.3.7,<1"
-filelock = ">=3.12.2,<4"
-platformdirs = ">=3.9.1,<5"
-
-[package.extras]
-docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
-test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
-
-[[package]]
-name = "websocket-client"
-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"},
-]
-
-[package.extras]
-docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"]
-optional = ["python-socks", "wsaccel"]
-test = ["websockets"]
-
-[[package]]
-name = "wheel"
-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"},
-]
-
-[package.extras]
-test = ["pytest (>=6.0.0)", "setuptools (>=65)"]
-
-[[package]]
-name = "wrapt"
-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"},
-    {file = "wrapt-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7"},
-    {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c"},
-    {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72"},
-    {file = "wrapt-1.17.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061"},
-    {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2"},
-    {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c"},
-    {file = "wrapt-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62"},
-    {file = "wrapt-1.17.2-cp310-cp310-win32.whl", hash = "sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563"},
-    {file = "wrapt-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f"},
-    {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58"},
-    {file = "wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda"},
-    {file = "wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438"},
-    {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a"},
-    {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000"},
-    {file = "wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6"},
-    {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b"},
-    {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662"},
-    {file = "wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72"},
-    {file = "wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317"},
-    {file = "wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3"},
-    {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925"},
-    {file = "wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392"},
-    {file = "wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40"},
-    {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d"},
-    {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b"},
-    {file = "wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98"},
-    {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82"},
-    {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae"},
-    {file = "wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9"},
-    {file = "wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9"},
-    {file = "wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991"},
-    {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125"},
-    {file = "wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998"},
-    {file = "wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5"},
-    {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8"},
-    {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6"},
-    {file = "wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc"},
-    {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2"},
-    {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b"},
-    {file = "wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504"},
-    {file = "wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a"},
-    {file = "wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845"},
-    {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192"},
-    {file = "wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b"},
-    {file = "wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0"},
-    {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306"},
-    {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb"},
-    {file = "wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681"},
-    {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6"},
-    {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6"},
-    {file = "wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f"},
-    {file = "wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555"},
-    {file = "wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c"},
-    {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9"},
-    {file = "wrapt-1.17.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119"},
-    {file = "wrapt-1.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6"},
-    {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9"},
-    {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a"},
-    {file = "wrapt-1.17.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2"},
-    {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a"},
-    {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04"},
-    {file = "wrapt-1.17.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f"},
-    {file = "wrapt-1.17.2-cp38-cp38-win32.whl", hash = "sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7"},
-    {file = "wrapt-1.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3"},
-    {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a"},
-    {file = "wrapt-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061"},
-    {file = "wrapt-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82"},
-    {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9"},
-    {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f"},
-    {file = "wrapt-1.17.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b"},
-    {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f"},
-    {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8"},
-    {file = "wrapt-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9"},
-    {file = "wrapt-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb"},
-    {file = "wrapt-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb"},
-    {file = "wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8"},
-    {file = "wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3"},
-]
-
-[[package]]
-name = "wsproto"
-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"},
-]
-
-[package.dependencies]
-h11 = ">=0.9.0,<1"
-
-[[package]]
-name = "zipp"
-version = "3.21.0"
-description = "Backport of pathlib-compatible object wrapper for zip files"
-optional = false
-python-versions = ">=3.9"
-groups = ["main"]
-markers = "python_version <= \"3.11\" and (platform_machine != \"ppc64le\" and platform_machine != \"s390x\") 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"},
-]
-
-[package.extras]
-check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
-cover = ["pytest-cov"]
-doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-enabler = ["pytest-enabler (>=2.2)"]
-test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"]
-type = ["pytest-mypy"]
-
-[metadata]
-lock-version = "2.1"
-python-versions = ">=3.10, <4.0"
-content-hash = "36de501672441a558232190e75c187dd92682b56a99fcd84dc2dc6ab78f7dfc8"

+ 126 - 0
pyi_hashes.json

@@ -0,0 +1,126 @@
+{
+  "reflex/__init__.pyi": "8a6d2350e96659846436792a5c7b772b",
+  "reflex/components/__init__.pyi": "76ba0a12cd3a7ba5ab6341a3ae81551f",
+  "reflex/components/base/__init__.pyi": "e9aaf47be1e1977eacee97b880c8f7de",
+  "reflex/components/base/app_wrap.pyi": "387fc7a0c2da8760d9449e2893e44eec",
+  "reflex/components/base/body.pyi": "2cc870cec4b1c28081dd40467752c2b7",
+  "reflex/components/base/document.pyi": "30377cdfb02b564f8de29b0473d2346c",
+  "reflex/components/base/error_boundary.pyi": "c56b591d14a92b99a1e97e04afe167d7",
+  "reflex/components/base/fragment.pyi": "603ee8e03af88d4a8ff6bc1fbce4e022",
+  "reflex/components/base/head.pyi": "893047aa32da553711db8f1345adb6b0",
+  "reflex/components/base/link.pyi": "396488afa3b7a5b0d0e6c5e89159f857",
+  "reflex/components/base/meta.pyi": "bc4b4fda6f022a517de339ffdd667e3b",
+  "reflex/components/base/script.pyi": "530cf8f47eb90082bf65942e8b5d745f",
+  "reflex/components/base/strict_mode.pyi": "d972e0ff2a6f961e7df90fc27b8bb51b",
+  "reflex/components/core/__init__.pyi": "44bcee7bc4e27e2f4f4707b843acf291",
+  "reflex/components/core/auto_scroll.pyi": "d3012d2a4ccaab8dfebf9aa484020f59",
+  "reflex/components/core/banner.pyi": "48d0eb86ae09e806ebe20d0edcc3cdb3",
+  "reflex/components/core/client_side_routing.pyi": "9be638a2b0e00b8181697e5dd6b45e4e",
+  "reflex/components/core/clipboard.pyi": "af76b623d593df3b16162033c597f920",
+  "reflex/components/core/debounce.pyi": "76d857eb814bc64625860a5f43e8b230",
+  "reflex/components/core/html.pyi": "b12117b42ef79ee90b6b4dec50baeb86",
+  "reflex/components/core/sticky.pyi": "c65131cf7c2312c68e1fddaa0cc27150",
+  "reflex/components/core/upload.pyi": "6fb89607ec8f8c1971f0dbd3453901eb",
+  "reflex/components/datadisplay/__init__.pyi": "cf087efa8b3960decc6b231cc986cfa9",
+  "reflex/components/datadisplay/code.pyi": "3d8f0ab4c2f123d7f80d15c7ebc553d9",
+  "reflex/components/datadisplay/dataeditor.pyi": "1b762071001161e4fdd1285263c33bb3",
+  "reflex/components/datadisplay/shiki_code_block.pyi": "87db7639bfa5cd53e1709e1363f93278",
+  "reflex/components/el/__init__.pyi": "09042a2db5e0637e99b5173430600522",
+  "reflex/components/el/element.pyi": "06ac2213b062119323291fa66a1ac19e",
+  "reflex/components/el/elements/__init__.pyi": "280ed457675f3720e34b560a3f617739",
+  "reflex/components/el/elements/base.pyi": "6e533348b5e1a88cf62fbb5a38dbd795",
+  "reflex/components/el/elements/forms.pyi": "2e7ab39bc7295b8594f38a2aa59c9610",
+  "reflex/components/el/elements/inline.pyi": "33d9d860e75dd8c4769825127ed363bb",
+  "reflex/components/el/elements/media.pyi": "addd6872281d65d44a484358b895432f",
+  "reflex/components/el/elements/metadata.pyi": "974a86d9f0662f6fc15a5bb4b3a87862",
+  "reflex/components/el/elements/other.pyi": "995a4fbf10bfdb7f48808210dfe413bd",
+  "reflex/components/el/elements/scripts.pyi": "cd5bd53c3a6b016fbb913aff36d63344",
+  "reflex/components/el/elements/sectioning.pyi": "65aa53b1372598ec1785616cb7016032",
+  "reflex/components/el/elements/tables.pyi": "e1282d8ddf4efa4c911ca104a907ee88",
+  "reflex/components/el/elements/typography.pyi": "00088c9c1b68a14e5a41d837e8fdf542",
+  "reflex/components/gridjs/datatable.pyi": "7fd1dd65ba143d60b7d42d1bb90a179d",
+  "reflex/components/lucide/icon.pyi": "a5521a8baf8d2d7281e3fdfe6ce7073b",
+  "reflex/components/markdown/markdown.pyi": "f2d0cbff02e0a26f201287fabe6fb738",
+  "reflex/components/moment/moment.pyi": "6dd0c7cee5f0f29bc11d830c697d7f92",
+  "reflex/components/next/base.pyi": "14aafd5b018a4bc9748a3c9980fcfe3e",
+  "reflex/components/next/image.pyi": "3a0d1970e69144e9c6806e68ab99f181",
+  "reflex/components/next/link.pyi": "cd913e10205314afe67101d9640e05cb",
+  "reflex/components/next/video.pyi": "09698418db651917630a7fefeb573fc2",
+  "reflex/components/plotly/plotly.pyi": "77afe88b405c3eae7058994d53a27946",
+  "reflex/components/radix/__init__.pyi": "8d586cbff1d7130d09476ac72ee73400",
+  "reflex/components/radix/primitives/__init__.pyi": "fe8715decf3e9ae471b56bba14e42cb3",
+  "reflex/components/radix/primitives/accordion.pyi": "b1482766c3c99ab40c2f446598fdb6a7",
+  "reflex/components/radix/primitives/base.pyi": "8b1dbf0b75cb29e873d611b83c9e4156",
+  "reflex/components/radix/primitives/drawer.pyi": "b6f8b17e1d0064d5609915546c722a81",
+  "reflex/components/radix/primitives/form.pyi": "79ddb679e0b3df814439ce993fcf355e",
+  "reflex/components/radix/primitives/progress.pyi": "c62a0c44e0d440701174fcca93bf8fbe",
+  "reflex/components/radix/primitives/slider.pyi": "c27e1a1180442e2e6e9d727560e8068c",
+  "reflex/components/radix/themes/__init__.pyi": "a15f9464ad99f248249ffa8e6deea4cf",
+  "reflex/components/radix/themes/base.pyi": "a3c3c3b72fd3d8f1e38990e5c461b682",
+  "reflex/components/radix/themes/color_mode.pyi": "435a51382eab6111aae1b26e79e9a473",
+  "reflex/components/radix/themes/components/__init__.pyi": "87bb9ffff641928562da1622d2ca5993",
+  "reflex/components/radix/themes/components/alert_dialog.pyi": "8e1dde62450296310a116ed066bd51e3",
+  "reflex/components/radix/themes/components/aspect_ratio.pyi": "1845813a034adfc1f5db8e0f6ffc1118",
+  "reflex/components/radix/themes/components/avatar.pyi": "b591cb8b31d5a9aea5413120a6a744d9",
+  "reflex/components/radix/themes/components/badge.pyi": "5e8f49fd9ff10c756d9afa54bfd3fd10",
+  "reflex/components/radix/themes/components/button.pyi": "201448dcdf735f24d8bd21112039c1ca",
+  "reflex/components/radix/themes/components/callout.pyi": "e2b5828f271a2d790e88bb965d0fcded",
+  "reflex/components/radix/themes/components/card.pyi": "fe42e0cbdf9eb34341f4bbba8a586b34",
+  "reflex/components/radix/themes/components/checkbox.pyi": "78bc26eabd6468a44f5139449a2c6208",
+  "reflex/components/radix/themes/components/checkbox_cards.pyi": "cc43c568aa42ffa3e693e5cd1acba156",
+  "reflex/components/radix/themes/components/checkbox_group.pyi": "e36603b9ea5f161070c5a0235c4411fa",
+  "reflex/components/radix/themes/components/context_menu.pyi": "cdf546723a84c99412d91ca63d4bb2df",
+  "reflex/components/radix/themes/components/data_list.pyi": "768e4c9222d37d90228309166a1c6ab3",
+  "reflex/components/radix/themes/components/dialog.pyi": "b51cb34dc6c90ccd07a2f9fc97eaf1c1",
+  "reflex/components/radix/themes/components/dropdown_menu.pyi": "34807c4ab4665932da664ab68dab0edf",
+  "reflex/components/radix/themes/components/hover_card.pyi": "cfa947d1edec4b17dc6f227783ca1cbc",
+  "reflex/components/radix/themes/components/icon_button.pyi": "560cc3a95a8f1a396c8c5fb916b0ee8b",
+  "reflex/components/radix/themes/components/inset.pyi": "828f3d3a5b8f7fd07597069c01aaa0a0",
+  "reflex/components/radix/themes/components/popover.pyi": "c953a42260a3b261eec772dba716d951",
+  "reflex/components/radix/themes/components/progress.pyi": "c880c6bb9803d47048f656dfa66a7c15",
+  "reflex/components/radix/themes/components/radio.pyi": "36fa5585440685a7d2dff40b50502840",
+  "reflex/components/radix/themes/components/radio_cards.pyi": "e9a0f27119322e6148946ae178edb7a9",
+  "reflex/components/radix/themes/components/radio_group.pyi": "ea3180940390e4b6eaf10670be5bc2fe",
+  "reflex/components/radix/themes/components/scroll_area.pyi": "83892be0b2c902d2147cbdb5e19310ab",
+  "reflex/components/radix/themes/components/segmented_control.pyi": "7be200991becc54cd885465656e2dfef",
+  "reflex/components/radix/themes/components/select.pyi": "655a5c2182a16121440e5ddbba2079d8",
+  "reflex/components/radix/themes/components/separator.pyi": "58a95aca75a556d349eb56f898bde680",
+  "reflex/components/radix/themes/components/skeleton.pyi": "d91615706e5efb81d97755decbbf5ae3",
+  "reflex/components/radix/themes/components/slider.pyi": "b87ee08b7edfe41eddf3d3c1cb71124e",
+  "reflex/components/radix/themes/components/spinner.pyi": "80766a7324b582221edb66ec46da0acb",
+  "reflex/components/radix/themes/components/switch.pyi": "f8256d2b50d15ab163649cfb05229750",
+  "reflex/components/radix/themes/components/table.pyi": "560ce8d920e03b450fe6b938f5f0fea0",
+  "reflex/components/radix/themes/components/tabs.pyi": "96ac1082651d2adc2a60a3af6e90c17f",
+  "reflex/components/radix/themes/components/text_area.pyi": "418d3df53eeca0723d83a93d81f16b12",
+  "reflex/components/radix/themes/components/text_field.pyi": "cdf0e08f5af0a5fce6b31787001f1dc3",
+  "reflex/components/radix/themes/components/tooltip.pyi": "6cd225ba10140e925752c74404336f27",
+  "reflex/components/radix/themes/layout/__init__.pyi": "9a52c5b283c864be70b51a8fd6120392",
+  "reflex/components/radix/themes/layout/base.pyi": "e9a5c1f376e66653ebcf5d2315f990f8",
+  "reflex/components/radix/themes/layout/box.pyi": "5a3c2339d74cc062358ec32b2c2c138c",
+  "reflex/components/radix/themes/layout/center.pyi": "29bde2c21a190ba7d7a382a1157f5aa7",
+  "reflex/components/radix/themes/layout/container.pyi": "4020c3dca660027b84d11cc4198393c4",
+  "reflex/components/radix/themes/layout/flex.pyi": "f814281a5635ad43dd1df23f8e356c66",
+  "reflex/components/radix/themes/layout/grid.pyi": "6062188367a2c253f014f916197c963d",
+  "reflex/components/radix/themes/layout/list.pyi": "804f7a36c103cd7a3e362d40a58e8d39",
+  "reflex/components/radix/themes/layout/section.pyi": "41895910072e023ed0fef6a8ad956046",
+  "reflex/components/radix/themes/layout/spacer.pyi": "029eb0eaa731bcdff7c496e0437e22b1",
+  "reflex/components/radix/themes/layout/stack.pyi": "3b0da99b00c826d087ed89fc67c595c1",
+  "reflex/components/radix/themes/typography/__init__.pyi": "ef0ba71353dcac1f3546de45f8721bae",
+  "reflex/components/radix/themes/typography/blockquote.pyi": "8ed6f1c5aa86743d1fb9488334af64fe",
+  "reflex/components/radix/themes/typography/code.pyi": "85e869bb61e3e0da9c244aea78e14193",
+  "reflex/components/radix/themes/typography/heading.pyi": "5a3b0b8e44bda0fce22c6b1a1f25e68e",
+  "reflex/components/radix/themes/typography/link.pyi": "45965d95b9f9b76f8f4a3084a5430194",
+  "reflex/components/radix/themes/typography/text.pyi": "e6aa0ca43ebbd42701a3c72c0312032e",
+  "reflex/components/react_player/audio.pyi": "972975ed0ba3e1dc4a867da20b11ae8e",
+  "reflex/components/react_player/react_player.pyi": "63ffffbc24907103f797dcfd85894107",
+  "reflex/components/react_player/video.pyi": "35ce5ad62e8bff17d9c09d27c362f8dc",
+  "reflex/components/recharts/__init__.pyi": "a52c9055e37c6ee25ded15688d45e8a5",
+  "reflex/components/recharts/cartesian.pyi": "34b15e8f5125b5a8145e3e04ed6418e4",
+  "reflex/components/recharts/charts.pyi": "b3d35de9cea86307ad2ab7d69ff2d06b",
+  "reflex/components/recharts/general.pyi": "5548fc494c29063c262ca7a7ef51dce8",
+  "reflex/components/recharts/polar.pyi": "8fb87fd69c9edf55998f11ea8ada76fb",
+  "reflex/components/recharts/recharts.pyi": "157acc830323075ffaf4f68d495d1787",
+  "reflex/components/sonner/toast.pyi": "0b6dc33413f30fdd043b89ec3c8c3f39",
+  "reflex/components/suneditor/editor.pyi": "284aa914b9bffe840db67ee68192eaf7",
+  "reflex/experimental/layout.pyi": "6398e779743963ef3e03396696b8ddfb"
+}

+ 98 - 67
pyproject.toml

@@ -1,81 +1,82 @@
-[tool.poetry]
+[project]
 name = "reflex"
-version = "0.7.2dev1"
+version = "0.7.7dev1"
 description = "Web apps in pure Python."
-license = "Apache-2.0"
+license = { text = "Apache-2.0" }
 authors = [
-  "Nikhil Rao <nikhil@reflex.dev>",
-  "Alek Petuskey <alek@reflex.dev>",
-  "Masen Furer <masen@reflex.dev>",
-  "Elijah Ahianyo <elijah@reflex.dev>",
-  "Thomas Brandého <thomas@reflex.dev>",
+  { name = "Nikhil Rao", email = "nikhil@reflex.dev" },
+  { name = "Alek Petuskey", email = "alek@reflex.dev" },
+  { name = "Masen Furer", email = "masen@reflex.dev" },
+  { name = "Elijah Ahianyo", email = "elijahahianyo@gmail.com" },
+  { name = "Thomas Brandeho", email = "thomas@reflex.dev" },
+  { name = "Khaleel Al-Adhami", email = "khaleel@reflex.dev" },
+]
+maintainers = [
+  { name = "Masen Furer", email = "masen@reflex.dev" },
+  { name = "Thomas Brandeho", email = "thomas@reflex.dev" },
+  { name = "Khaleel Al-Adhami", email = "khaleel@reflex.dev" },
 ]
 readme = "README.md"
-homepage = "https://reflex.dev"
-repository = "https://github.com/reflex-dev/reflex"
-documentation = "https://reflex.dev/docs/getting-started/introduction"
 keywords = ["web", "framework"]
-classifiers = ["Development Status :: 4 - Beta"]
+requires-python = ">=3.10,<4.0"
+dependencies = [
+  "alembic >=1.15.2,<2.0",
+  "distro >=1.9.0,<2.0; platform_system == 'Linux'",
+  "fastapi >=0.115.0",
+  "granian[reload] >=2.2.3",
+  "gunicorn >=23.0.0,<24.0.0",
+  "httpx >=0.28.0,<1.0",
+  "jinja2 >=3.1.2,<4.0",
+  "packaging >=24.2,<25.0",
+  "platformdirs >=4.3.7,<5.0",
+  "psutil >=7.0.0,<8.0",
+  "pydantic >=1.10.21,<3.0",
+  "python-socketio >=5.12.0,<6.0",
+  "python-multipart >=0.0.20,<1.0",
+  "redis >=5.2.1,<6.0",
+  "reflex-hosting-cli >=0.1.38",
+  "rich >=13.0.0,<14.0",
+  "sqlmodel >=0.0.24,<0.1",
+  "typer >=0.15.2,<1.0",
+  "typing_extensions >=4.13.0",
+  "uvicorn >=0.34.0",
+  "wrapt >=1.17.0,<2.0",
+]
+classifiers = [
+  "Development Status :: 4 - Beta",
+  "License :: OSI Approved :: Apache Software License",
+  "Programming Language :: Python :: 3",
+  "Programming Language :: Python :: 3.10",
+  "Programming Language :: Python :: 3.11",
+  "Programming Language :: Python :: 3.12",
+  "Programming Language :: Python :: 3.13",
+]
 
-[tool.poetry.dependencies]
-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"
-psutil = ">=5.9.4,<7.0"
-pydantic = ">=1.10.21,<3.0"
-python-multipart = ">=0.0.5,<0.1"
-python-socketio = ">=5.7.0,<6.0"
-redis = ">=4.3.5,<6.0"
-rich = ">=13.0.0,<14.0"
-sqlmodel = ">=0.0.14,<0.1"
-typer = ">=0.15.1,<1.0"
-uvicorn = ">=0.20.0"
-starlette-admin = ">=0.11.0,<1.0"
-alembic = ">=1.11.1,<2.0"
-platformdirs = ">=3.10.0,<5.0"
-distro = { version = ">=1.8.0,<2.0", platform = "linux" }
-python-engineio = "!=4.6.0"
-wrapt = ">=1.17.0,<2.0"
-packaging = ">=23.1,<25.0"
-reflex-hosting-cli = ">=0.1.29"
-charset-normalizer = ">=3.3.2,<4.0"
-wheel = ">=0.42.0,<1.0"
-build = ">=1.0.3,<2.0"
-setuptools = ">=75.0"
-httpx = ">=0.25.1,<1.0"
-twine = ">=4.0.0,<7.0"
-tomlkit = ">=0.12.4,<1.0"
-lazy_loader = ">=0.4"
-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.394, <1.2"
-darglint = ">=1.8.1,<2.0"
-dill = ">=0.3.8"
-toml = ">=0.10.2,<1.0"
-pytest-asyncio = ">=0.24.0"
-pytest-cov = ">=4.0.0,<7.0"
-ruff = "0.9.6"
-pandas = ">=2.1.1,<3.0"
-pillow = ">=10.0.0,<12.0"
-plotly = ">=5.13.0,<6.0"
-asynctest = ">=0.13.0,<1.0"
-pre-commit = ">=3.2.1"
-selenium = ">=4.11.0,<5.0"
-pytest-benchmark = ">=4.0.0,<6.0"
-playwright = ">=1.46.0"
-pytest-playwright = ">=0.5.1"
-pytest-codspeed = "^3.1.2"
+[project.urls]
+homepage = "https://reflex.dev"
+repository = "https://github.com/reflex-dev/reflex"
+documentation = "https://reflex.dev/docs/getting-started/introduction"
 
-[tool.poetry.scripts]
+[project.scripts]
 reflex = "reflex.reflex:cli"
 
 [build-system]
-requires = ["poetry-core>=1.5.1"]
-build-backend = "poetry.core.masonry.api"
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.hatch.build]
+include = ["reflex"]
+
+[tool.hatch.build.targets.sdist]
+artifacts = ["*.pyi"]
+
+[tool.hatch.build.targets.wheel]
+artifacts = ["*.pyi"]
+
+[tool.hatch.build.hooks.custom]
+dependencies = ["plotly", "ruff"]
+require-runtime-dependencies = true
 
 [tool.pyright]
 reportIncompatibleMethodOverride = false
@@ -133,5 +134,35 @@ asyncio_default_fixture_loop_scope = "function"
 asyncio_mode = "auto"
 
 [tool.codespell]
-skip = "docs/*,*.html,examples/*, *.pyi, poetry.lock"
+skip = "docs/*,*.html,examples/*, *.pyi, poetry.lock, uv.lock"
 ignore-words-list = "te, TreeE"
+
+[dependency-groups]
+dev = [
+  "asynctest >=0.13",
+  "darglint >=1.8",
+  "dill >=0.3",
+  "hatchling >=1.27",
+  "libsass >=0.23",
+  "numpy >=2.2",
+  "pandas >=2.2",
+  "pillow >=11",
+  "playwright >=1.51",
+  "plotly >=6.0",
+  "pre-commit >=4.2",
+  "psycopg[binary] >=3.2",
+  "pyright >=1.1.399",
+  "pytest >=8.3",
+  "pytest-asyncio >=0.26",
+  "pytest-benchmark >=5.1",
+  "pytest-codspeed >=3.2",
+  "pytest-cov >=6.1",
+  "pytest-mock >=3.14",
+  "pytest-playwright >=0.7",
+  "pytest-retry >=1.7",
+  "pytest-split >=0.10",
+  "python-dotenv >=1",
+  "ruff >=0.11",
+  "selenium >=4.31",
+  "starlette-admin >=0.14",
+]

+ 1 - 1
reflex/.templates/jinja/web/pages/_app.js.jinja2

@@ -2,7 +2,7 @@
 {% from "web/pages/macros.js.jinja2" import renderHooks %}
 
 {% block early_imports %}
-import '$/styles/styles.css'
+import '$/styles/__reflex_global_styles.css'
 {% endblock %}
 
 {% block declaration %}

+ 6 - 3
reflex/.templates/jinja/web/pages/custom_component.js.jinja2

@@ -1,11 +1,14 @@
 {% extends "web/pages/base_page.js.jinja2" %}
 {% from "web/pages/macros.js.jinja2" import renderHooks %}
-{% block export %}
-{% for component in components %}
 
-{% for custom_code in component.custom_code %}
+{% block declaration %}
+{% for custom_code in custom_codes %}
 {{custom_code}}
 {% endfor %}
+{% endblock %}
+
+{% block export %}
+{% for component in components %}
 
 export const {{component.name}} = memo(({ {{-component.props|join(", ")-}} }) => {
     {{ renderHooks(component.hooks) }}

+ 10 - 2
reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js

@@ -1,5 +1,5 @@
 import { useTheme } from "next-themes";
-import { useEffect, useState } from "react";
+import { useRef, useEffect, useState } from "react";
 import {
   ColorModeContext,
   defaultColorMode,
@@ -11,8 +11,16 @@ export default function RadixThemesColorModeProvider({ children }) {
   const { theme, resolvedTheme, setTheme } = useTheme();
   const [rawColorMode, setRawColorMode] = useState(defaultColorMode);
   const [resolvedColorMode, setResolvedColorMode] = useState(
-    defaultColorMode === "dark" ? "dark" : "light"
+    defaultColorMode === "dark" ? "dark" : "light",
   );
+  const firstUpdate = useRef(true);
+  useEffect(() => {
+    if (firstUpdate.current) {
+      firstUpdate.current = false;
+      setRawColorMode(theme);
+      setResolvedColorMode(resolvedTheme);
+    }
+  });
 
   useEffect(() => {
     if (isDevMode) {

+ 26 - 21
reflex/.templates/web/components/shiki/code.js

@@ -1,5 +1,5 @@
-import { useEffect, useState } from "react"
-import { codeToHtml} from "shiki"
+import { useEffect, useState } from "react";
+import { codeToHtml } from "shiki";
 
 /**
  * Code component that uses Shiki to convert code to HTML and render it.
@@ -12,23 +12,28 @@ import { codeToHtml} from "shiki"
  * @param divProps - Additional properties to be passed to the div element.
  * @returns The rendered code block.
  */
-export function Code ({code, theme, language, transformers, decorations, ...divProps}) {
-    const [codeResult, setCodeResult] = useState("")
-    useEffect(() => {
-        async function fetchCode() {
-          const result = await codeToHtml(code, {
-            lang: language,
-            theme,
-            transformers,
-            decorations
-          });
-          setCodeResult(result);
-        }
-        fetchCode();
-      }, [code, language, theme, transformers, decorations]
-
-    )
-    return (
-        <div dangerouslySetInnerHTML={{__html: codeResult}} {...divProps}  ></div>
-    )
+export function Code({
+  code,
+  theme,
+  language,
+  transformers,
+  decorations,
+  ...divProps
+}) {
+  const [codeResult, setCodeResult] = useState("");
+  useEffect(() => {
+    async function fetchCode() {
+      const result = await codeToHtml(code, {
+        lang: language,
+        theme,
+        transformers,
+        decorations,
+      });
+      setCodeResult(result);
+    }
+    fetchCode();
+  }, [code, language, theme, transformers, decorations]);
+  return (
+    <div dangerouslySetInnerHTML={{ __html: codeResult }} {...divProps}></div>
+  );
 }

+ 1 - 1
reflex/.templates/web/postcss.config.js

@@ -4,4 +4,4 @@ module.exports = {
     tailwindcss: {},
     autoprefixer: {},
   },
-}
+};

+ 18 - 16
reflex/.templates/web/utils/client_side_routing.js

@@ -10,32 +10,34 @@ import { useRouter } from "next/router";
  * @returns {boolean} routeNotFound - true if the current route is an actual 404
  */
 export const useClientSideRouting = () => {
-  const [routeNotFound, setRouteNotFound] = useState(false)
-  const didRedirect = useRef(false)
-  const router = useRouter()
+  const [routeNotFound, setRouteNotFound] = useState(false);
+  const didRedirect = useRef(false);
+  const router = useRouter();
   useEffect(() => {
     if (
       router.isReady &&
-      !didRedirect.current  // have not tried redirecting yet
+      !didRedirect.current // have not tried redirecting yet
     ) {
-      didRedirect.current = true  // never redirect twice to avoid "Hard Navigate" error
+      didRedirect.current = true; // never redirect twice to avoid "Hard Navigate" error
       // attempt to redirect to the route in the browser address bar once
-      router.replace({
+      router
+        .replace({
           pathname: window.location.pathname,
           query: window.location.search.slice(1),
-      }).then(()=>{
+        })
+        .then(() => {
           // Check if the current route is /404
-        if (router.pathname === '/404') {
-          setRouteNotFound(true); // Mark as an actual 404
-        }
-    })
-      .catch((e) => {
-        setRouteNotFound(true)  // navigation failed, so this is a real 404
-      })
+          if (router.pathname === "/404") {
+            setRouteNotFound(true); // Mark as an actual 404
+          }
+        })
+        .catch((e) => {
+          setRouteNotFound(true); // navigation failed, so this is a real 404
+        });
     }
   }, [router.isReady]);
 
   // Return the reactive bool, to avoid flashing 404 page until we know for sure
   // the route is not found.
-  return routeNotFound
-}
+  return routeNotFound;
+};

+ 1 - 1
reflex/.templates/web/utils/helpers/dataeditor.js

@@ -48,7 +48,7 @@ export function formatCell(value, column) {
       };
     default:
       console.log(
-        "Warning: column.type is undefined for column.title=" + column.title
+        "Warning: column.type is undefined for column.title=" + column.title,
       );
       return {
         kind: GridCellKind.Text,

+ 30 - 30
reflex/.templates/web/utils/helpers/range.js

@@ -1,43 +1,43 @@
 /**
  * Simulate the python range() builtin function.
  * inspired by https://dev.to/guyariely/using-python-range-in-javascript-337p
- * 
+ *
  * If needed outside of an iterator context, use `Array.from(range(10))` or
  * spread syntax `[...range(10)]` to get an array.
- * 
+ *
  * @param {number} start: the start or end of the range.
  * @param {number} stop: the end of the range.
  * @param {number} step: the step of the range.
  * @returns {object} an object with a Symbol.iterator method over the range
  */
 export default function range(start, stop, step) {
-    return {
-      [Symbol.iterator]() {
-        if (stop === undefined) {
-          stop = start;
-          start = 0;
-        }
-        if (step === undefined) {
-          step = 1;
-        }
-  
-        let i = start - step;
-  
-        return {
-          next() {
-            i += step;
-            if ((step > 0 && i < stop) || (step < 0 && i > stop)) {
-              return {
-                value: i,
-                done: false,
-              };
-            }
+  return {
+    [Symbol.iterator]() {
+      if (stop === undefined) {
+        stop = start;
+        start = 0;
+      }
+      if (step === undefined) {
+        step = 1;
+      }
+
+      let i = start - step;
+
+      return {
+        next() {
+          i += step;
+          if ((step > 0 && i < stop) || (step < 0 && i > stop)) {
             return {
-              value: undefined,
-              done: true,
+              value: i,
+              done: false,
             };
-          },
-        };
-      },
-    };
-  }
+          }
+          return {
+            value: undefined,
+            done: true,
+          };
+        },
+      };
+    },
+  };
+}

+ 37 - 6
reflex/.templates/web/utils/state.js

@@ -179,7 +179,7 @@ export const applyEvent = async (event, socket) => {
   // Handle special events
   if (event.name == "_redirect") {
     if (event.payload.external) {
-      window.open(event.payload.path, "_blank");
+      window.open(event.payload.path, "_blank", "noopener");
     } else if (event.payload.replace) {
       Router.replace(event.payload.path);
     } else {
@@ -352,8 +352,18 @@ export const applyRestEvent = async (event, socket) => {
  * Queue events to be processed and trigger processing of queue.
  * @param events Array of events to queue.
  * @param socket The socket object to send the event on.
+ * @param prepend Whether to place the events at the beginning of the queue.
  */
-export const queueEvents = async (events, socket) => {
+export const queueEvents = async (events, socket, prepend) => {
+  if (prepend) {
+    // Drain the existing queue and place it after the given events.
+    events = [
+      ...events,
+      ...Array.from({ length: event_queue.length }).map(() =>
+        event_queue.shift(),
+      ),
+    ];
+  }
   event_queue.push(...events);
   await processEvent(socket.current);
 };
@@ -441,6 +451,13 @@ export const connect = async (
     }
   }
 
+  const disconnectTrigger = (event) => {
+    if (socket.current?.connected) {
+      console.log("Disconnect websocket on unload");
+      socket.current.disconnect();
+    }
+  };
+
   const pagehideHandler = (event) => {
     if (event.persisted && socket.current?.connected) {
       console.log("Disconnect backend before bfcache on navigation");
@@ -452,6 +469,8 @@ export const connect = async (
   socket.current.on("connect", () => {
     setConnectErrors([]);
     window.addEventListener("pagehide", pagehideHandler);
+    window.addEventListener("beforeunload", disconnectTrigger);
+    window.addEventListener("unload", disconnectTrigger);
   });
 
   socket.current.on("connect_error", (error) => {
@@ -461,6 +480,8 @@ export const connect = async (
   // When the socket disconnects reset the event_processing flag
   socket.current.on("disconnect", () => {
     event_processing = false;
+    window.removeEventListener("unload", disconnectTrigger);
+    window.removeEventListener("beforeunload", disconnectTrigger);
     window.removeEventListener("pagehide", pagehideHandler);
   });
 
@@ -477,7 +498,7 @@ export const connect = async (
   });
   socket.current.on("reload", async (event) => {
     event_processing = false;
-    queueEvents([...initialEvents(), event], socket);
+    queueEvents([...initialEvents(), event], socket, true);
   });
 
   document.addEventListener("visibilitychange", checkVisibility);
@@ -773,9 +794,8 @@ export const useEventLoop = (
   const sentHydrate = useRef(false); // Avoid double-hydrate due to React strict-mode
   useEffect(() => {
     if (router.isReady && !sentHydrate.current) {
-      const events = initial_events();
-      addEvents(
-        events.map((e) => ({
+      queueEvents(
+        initial_events().map((e) => ({
           ...e,
           router_data: (({ pathname, query, asPath }) => ({
             pathname,
@@ -783,6 +803,8 @@ export const useEventLoop = (
             asPath,
           }))(router),
         })),
+        socket,
+        true,
       );
       sentHydrate.current = true;
     }
@@ -926,6 +948,15 @@ export const isTrue = (val) => {
   return Boolean(val);
 };
 
+/***
+ * Check if a value is not null or undefined.
+ * @param val The value to check.
+ * @returns True if the value is not null or undefined, false otherwise.
+ */
+export const isNotNullOrUndefined = (val) => {
+  return val ?? undefined !== undefined;
+};
+
 /**
  * Get the value from a ref.
  * @param ref The ref to get the value from.

+ 2 - 1
reflex/__init__.py

@@ -344,6 +344,7 @@ _MAPPING: dict = {
     "istate.wrappers": ["get_state"],
     "style": ["Style", "toggle_color_mode"],
     "utils.imports": ["ImportDict", "ImportVar"],
+    "utils.misc": ["run_in_thread"],
     "utils.serializers": ["serializer"],
     "vars": ["Var", "field", "Field"],
 }
@@ -369,5 +370,5 @@ getattr, __dir__, __all__ = lazy_loader.attach(
 )
 
 
-def __getattr__(name: ModuleType | Any):
+def __getattr__(name: str):
     return getattr(name)

+ 0 - 214
reflex/__init__.pyi

@@ -1,214 +0,0 @@
-"""Stub file for reflex/__init__.py"""
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-
-from reflex.utils import compat
-
-from . import admin as admin
-from . import app as app
-from . import base as base
-from . import compiler as compiler
-from . import components as components
-from . import config as config
-from . import model as model
-from . import style as style
-from . import testing as testing
-from . import utils as utils
-from . import vars as vars
-from .admin import AdminDash as AdminDash
-from .app import App as App
-from .app import UploadFile as UploadFile
-from .assets import asset as asset
-from .base import Base as Base
-from .components import el as el
-from .components import lucide as lucide
-from .components import next as next
-from .components import radix as radix
-from .components import recharts as recharts
-from .components.base.fragment import Fragment as Fragment
-from .components.base.fragment import fragment as fragment
-from .components.base.script import Script as Script
-from .components.base.script import script as script
-from .components.component import Component as Component
-from .components.component import ComponentNamespace as ComponentNamespace
-from .components.component import NoSSRComponent as NoSSRComponent
-from .components.component import memo as memo
-from .components.core.auto_scroll import auto_scroll as auto_scroll
-from .components.core.banner import connection_banner as connection_banner
-from .components.core.banner import connection_modal as connection_modal
-from .components.core.breakpoints import breakpoints as breakpoints
-from .components.core.clipboard import clipboard as clipboard
-from .components.core.colors import color as color
-from .components.core.cond import color_mode_cond as color_mode_cond
-from .components.core.cond import cond as cond
-from .components.core.debounce import debounce_input as debounce_input
-from .components.core.foreach import foreach as foreach
-from .components.core.html import html as html
-from .components.core.match import match as match
-from .components.core.responsive import desktop_only as desktop_only
-from .components.core.responsive import mobile_and_tablet as mobile_and_tablet
-from .components.core.responsive import mobile_only as mobile_only
-from .components.core.responsive import tablet_and_desktop as tablet_and_desktop
-from .components.core.responsive import tablet_only as tablet_only
-from .components.core.upload import cancel_upload as cancel_upload
-from .components.core.upload import clear_selected_files as clear_selected_files
-from .components.core.upload import get_upload_dir as get_upload_dir
-from .components.core.upload import get_upload_url as get_upload_url
-from .components.core.upload import selected_files as selected_files
-from .components.core.upload import upload as upload
-from .components.datadisplay.code import code_block as code_block
-from .components.datadisplay.dataeditor import data_editor as data_editor
-from .components.datadisplay.dataeditor import data_editor_theme as data_editor_theme
-from .components.datadisplay.logo import logo as logo
-from .components.el.elements.media import image as image
-from .components.gridjs import data_table as data_table
-from .components.lucide import icon as icon
-from .components.markdown import markdown as markdown
-from .components.moment import MomentDelta as MomentDelta
-from .components.moment import moment as moment
-from .components.plotly import plotly as plotly
-from .components.radix.primitives.accordion import accordion as accordion
-from .components.radix.primitives.drawer import drawer as drawer
-from .components.radix.primitives.form import form as form
-from .components.radix.themes.base import theme as theme
-from .components.radix.themes.base import theme_panel as theme_panel
-from .components.radix.themes.color_mode import color_mode as color_mode
-from .components.radix.themes.components.alert_dialog import (
-    alert_dialog as alert_dialog,
-)
-from .components.radix.themes.components.aspect_ratio import (
-    aspect_ratio as aspect_ratio,
-)
-from .components.radix.themes.components.avatar import avatar as avatar
-from .components.radix.themes.components.badge import badge as badge
-from .components.radix.themes.components.button import button as button
-from .components.radix.themes.components.callout import callout as callout
-from .components.radix.themes.components.card import card as card
-from .components.radix.themes.components.checkbox import checkbox as checkbox
-from .components.radix.themes.components.checkbox_cards import (
-    checkbox_cards as checkbox_cards,
-)
-from .components.radix.themes.components.checkbox_group import (
-    checkbox_group as checkbox_group,
-)
-from .components.radix.themes.components.context_menu import (
-    context_menu as context_menu,
-)
-from .components.radix.themes.components.data_list import data_list as data_list
-from .components.radix.themes.components.dialog import dialog as dialog
-from .components.radix.themes.components.dropdown_menu import (
-    dropdown_menu as dropdown_menu,
-)
-from .components.radix.themes.components.dropdown_menu import menu as menu
-from .components.radix.themes.components.hover_card import hover_card as hover_card
-from .components.radix.themes.components.icon_button import icon_button as icon_button
-from .components.radix.themes.components.inset import inset as inset
-from .components.radix.themes.components.popover import popover as popover
-from .components.radix.themes.components.progress import progress as progress
-from .components.radix.themes.components.radio_cards import radio_cards as radio_cards
-from .components.radix.themes.components.radio_group import radio as radio
-from .components.radix.themes.components.radio_group import radio_group as radio_group
-from .components.radix.themes.components.scroll_area import scroll_area as scroll_area
-from .components.radix.themes.components.segmented_control import (
-    segmented_control as segmented_control,
-)
-from .components.radix.themes.components.select import select as select
-from .components.radix.themes.components.separator import divider as divider
-from .components.radix.themes.components.separator import separator as separator
-from .components.radix.themes.components.skeleton import skeleton as skeleton
-from .components.radix.themes.components.slider import slider as slider
-from .components.radix.themes.components.spinner import spinner as spinner
-from .components.radix.themes.components.switch import switch as switch
-from .components.radix.themes.components.table import table as table
-from .components.radix.themes.components.tabs import tabs as tabs
-from .components.radix.themes.components.text_area import text_area as text_area
-from .components.radix.themes.components.text_field import input as input
-from .components.radix.themes.components.text_field import text_field as text_field
-from .components.radix.themes.components.tooltip import tooltip as tooltip
-from .components.radix.themes.layout.box import box as box
-from .components.radix.themes.layout.center import center as center
-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: 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
-from .components.radix.themes.layout.spacer import spacer as spacer
-from .components.radix.themes.layout.stack import hstack as hstack
-from .components.radix.themes.layout.stack import stack as stack
-from .components.radix.themes.layout.stack import vstack as vstack
-from .components.radix.themes.typography.blockquote import blockquote as blockquote
-from .components.radix.themes.typography.code import code as code
-from .components.radix.themes.typography.heading import heading as heading
-from .components.radix.themes.typography.link import link as link
-from .components.radix.themes.typography.text import text as text
-from .components.react_player import audio as audio
-from .components.react_player import video as video
-from .components.sonner.toast import toast as toast
-from .components.suneditor import EditorButtonList as EditorButtonList
-from .components.suneditor import EditorOptions as EditorOptions
-from .components.suneditor import editor as editor
-from .config import Config as Config
-from .config import DBConfig as DBConfig
-from .constants import Env as Env
-from .constants.colors import Color as Color
-from .event import EventChain as EventChain
-from .event import EventHandler as EventHandler
-from .event import call_function as call_function
-from .event import call_script as call_script
-from .event import clear_local_storage as clear_local_storage
-from .event import clear_session_storage as clear_session_storage
-from .event import console_log as console_log
-from .event import download as download
-from .event import event as event
-from .event import noop as noop
-from .event import prevent_default as prevent_default
-from .event import redirect as redirect
-from .event import remove_cookie as remove_cookie
-from .event import remove_local_storage as remove_local_storage
-from .event import remove_session_storage as remove_session_storage
-from .event import run_script as run_script
-from .event import scroll_to as scroll_to
-from .event import set_clipboard as set_clipboard
-from .event import set_focus as set_focus
-from .event import set_value as set_value
-from .event import stop_propagation as stop_propagation
-from .event import upload_files as upload_files
-from .event import window_alert as window_alert
-from .experimental import _x as _x
-from .istate.storage import Cookie as Cookie
-from .istate.storage import LocalStorage as LocalStorage
-from .istate.storage import SessionStorage as SessionStorage
-from .istate.wrappers import get_state as get_state
-from .middleware import Middleware as Middleware
-from .middleware import middleware as middleware
-from .model import Model as Model
-from .model import asession as asession
-from .model import session as session
-from .page import page as page
-from .state import ComponentState as ComponentState
-from .state import State as State
-from .state import dynamic as dynamic
-from .state import var as var
-from .style import Style as Style
-from .style import toggle_color_mode as toggle_color_mode
-from .utils.imports import ImportDict as ImportDict
-from .utils.imports import ImportVar as ImportVar
-from .utils.serializers import serializer as serializer
-from .vars import Field as Field
-from .vars import Var as Var
-from .vars import field as field
-
-del compat
-RADIX_THEMES_MAPPING: dict
-RADIX_THEMES_COMPONENTS_MAPPING: dict
-RADIX_THEMES_LAYOUT_MAPPING: dict
-RADIX_THEMES_TYPOGRAPHY_MAPPING: dict
-RADIX_PRIMITIVES_MAPPING: dict
-RADIX_PRIMITIVES_SHORTCUT_MAPPING: dict
-COMPONENTS_CORE_MAPPING: dict
-COMPONENTS_BASE_MAPPING: dict
-RADIX_MAPPING: dict

+ 6 - 2
reflex/admin.py

@@ -1,8 +1,12 @@
 """The Reflex Admin Dashboard."""
 
+from __future__ import annotations
+
 from dataclasses import dataclass, field
+from typing import TYPE_CHECKING
 
-from starlette_admin.base import BaseAdmin as Admin
+if TYPE_CHECKING:
+    from starlette_admin.base import BaseAdmin as Admin
 
 
 @dataclass
@@ -11,4 +15,4 @@ class AdminDash:
 
     models: list = field(default_factory=list)
     view_overrides: dict = field(default_factory=dict)
-    admin: Admin | None = None
+    admin: "Admin | None" = None

+ 47 - 14
reflex/app.py

@@ -40,8 +40,6 @@ from rich.progress import MofNCompleteColumn, Progress, TimeElapsedColumn
 from socketio import ASGIApp, AsyncNamespace, AsyncServer
 from starlette.datastructures import Headers
 from starlette.datastructures import UploadFile as StarletteUploadFile
-from starlette_admin.contrib.sqla.admin import Admin
-from starlette_admin.contrib.sqla.view import ModelView
 
 from reflex import constants
 from reflex.admin import AdminDash
@@ -114,9 +112,11 @@ from reflex.utils.imports import ImportVar
 if TYPE_CHECKING:
     from reflex.vars import Var
 
+    # Define custom types.
+    ComponentCallable = Callable[[], Component | tuple[Component, ...] | str | Var]
+else:
+    ComponentCallable = Callable[[], Component | tuple[Component, ...] | str]
 
-# Define custom types.
-ComponentCallable = Callable[[], Component]
 Reducer = Callable[[Event], Coroutine[Any, Any, StateUpdate]]
 
 
@@ -293,6 +293,7 @@ class UnevaluatedPage:
     image: str
     on_load: EventType[()] | None
     meta: list[dict[str, str]]
+    context: dict[str, Any] | None
 
 
 @dataclasses.dataclass()
@@ -443,6 +444,8 @@ class App(MiddlewareMixin, LifespanMixin):
                 "rx.BaseState cannot be subclassed directly. Use rx.State instead"
             )
 
+        get_config(reload=True)
+
         if "breakpoints" in self.style:
             set_breakpoints(self.style.pop("breakpoints"))
 
@@ -498,9 +501,9 @@ class App(MiddlewareMixin, LifespanMixin):
                     else config.cors_allowed_origins
                 ),
                 cors_credentials=True,
-                max_http_buffer_size=constants.POLLING_MAX_HTTP_BUFFER_SIZE,
-                ping_interval=constants.Ping.INTERVAL,
-                ping_timeout=constants.Ping.TIMEOUT,
+                max_http_buffer_size=environment.REFLEX_SOCKET_MAX_HTTP_BUFFER_SIZE.get(),
+                ping_interval=environment.REFLEX_SOCKET_INTERVAL.get(),
+                ping_timeout=environment.REFLEX_SOCKET_TIMEOUT.get(),
                 json=SimpleNamespace(
                     dumps=staticmethod(format.json_dumps),
                     loads=staticmethod(json.loads),
@@ -576,6 +579,22 @@ class App(MiddlewareMixin, LifespanMixin):
         """
         if not self.api:
             raise ValueError("The app has not been initialized.")
+
+        # For py3.9 compatibility when redis is used, we MUST add any decorator pages
+        # before compiling the app in a thread to avoid event loop error (REF-2172).
+        self._apply_decorated_pages()
+
+        compile_future = concurrent.futures.ThreadPoolExecutor(max_workers=1).submit(
+            self._compile
+        )
+        compile_future.add_done_callback(
+            # Force background compile errors to print eagerly
+            lambda f: f.result()
+        )
+        # Wait for the compile to finish in prod mode to ensure all optional endpoints are mounted.
+        if is_prod_mode():
+            compile_future.result()
+
         return self.api
 
     def _add_default_endpoints(self):
@@ -663,6 +682,7 @@ class App(MiddlewareMixin, LifespanMixin):
         image: str = constants.DefaultPage.IMAGE,
         on_load: EventType[()] | None = None,
         meta: list[dict[str, str]] = constants.DefaultPage.META_LIST,
+        context: dict[str, Any] | None = None,
     ):
         """Add a page to the app.
 
@@ -677,6 +697,7 @@ class App(MiddlewareMixin, LifespanMixin):
             image: The image to display on the page.
             on_load: The event handler(s) that will be called each time the page load.
             meta: The metadata of the page.
+            context: Values passed to page for custom page-specific logic.
 
         Raises:
             PageValueError: When the component is not set for a non-404 page.
@@ -744,6 +765,7 @@ class App(MiddlewareMixin, LifespanMixin):
             image=image,
             on_load=on_load,
             meta=meta,
+            context=context,
         )
 
     def _compile_page(self, route: str, save_page: bool = True):
@@ -867,6 +889,12 @@ class App(MiddlewareMixin, LifespanMixin):
 
     def _setup_admin_dash(self):
         """Setup the admin dash."""
+        try:
+            from starlette_admin.contrib.sqla.admin import Admin
+            from starlette_admin.contrib.sqla.view import ModelView
+        except ImportError:
+            return
+
         # Get the admin dash.
         if not self.api:
             return
@@ -909,6 +937,9 @@ class App(MiddlewareMixin, LifespanMixin):
             and i != ""
             and any(tag.install for tag in tags)
         }
+        pinned = {i.rpartition("@")[0] for i in page_imports if "@" in i}
+        page_imports = {i for i in page_imports if i not in pinned}
+
         frontend_packages = get_config().frontend_packages
         _frontend_packages = []
         for package in frontend_packages:
@@ -952,7 +983,7 @@ class App(MiddlewareMixin, LifespanMixin):
         # Check the nocompile file.
         if nocompile.exists():
             # Delete the nocompile file
-            nocompile.unlink()
+            nocompile.unlink(missing_ok=True)
             return False
 
         # By default, compile the app.
@@ -1063,7 +1094,7 @@ class App(MiddlewareMixin, LifespanMixin):
                 with stateful_pages_marker.open("r") as f:
                     stateful_pages = json.load(f)
                 for route in stateful_pages:
-                    console.info(f"BE Evaluating stateful page: {route}")
+                    console.debug(f"BE Evaluating stateful page: {route}")
                     self._compile_page(route, save_page=False)
                 self._enable_state()
             self._add_optional_endpoints()
@@ -1092,8 +1123,6 @@ class App(MiddlewareMixin, LifespanMixin):
         if config.react_strict_mode:
             app_wrappers[(200, "StrictMode")] = StrictMode.create()
 
-        should_compile = self._should_compile()
-
         if not should_compile:
             with console.timing("Evaluate Pages (Backend)"):
                 for route in self._unevaluated_pages:
@@ -1210,13 +1239,15 @@ class App(MiddlewareMixin, LifespanMixin):
             custom_components |= component._get_all_custom_components()
 
         if self.error_boundary:
+            from reflex.compiler.compiler import into_component
+
             console.deprecate(
                 feature_name="App.error_boundary",
                 reason="Use app_wraps instead.",
                 deprecation_version="0.7.1",
                 removal_version="0.8.0",
             )
-            app_wrappers[(55, "ErrorBoundary")] = self.error_boundary()
+            app_wrappers[(55, "ErrorBoundary")] = into_component(self.error_boundary)
 
         # Perform auto-memoization of stateful components.
         with console.timing("Auto-memoize StatefulComponents"):
@@ -1242,7 +1273,9 @@ class App(MiddlewareMixin, LifespanMixin):
             compiler.compile_document_root(
                 self.head_components,
                 html_lang=self.html_lang,
-                html_custom_attrs=self.html_custom_attrs,  # pyright: ignore [reportArgumentType]
+                html_custom_attrs=(
+                    {**self.html_custom_attrs} if self.html_custom_attrs else {}
+                ),
             )
         )
 
@@ -1407,7 +1440,7 @@ class App(MiddlewareMixin, LifespanMixin):
         async with self.state_manager.modify_state(token) as state:
             # No other event handler can modify the state while in this context.
             yield state
-            delta = state.get_delta()
+            delta = await state._get_resolved_delta()
             if delta:
                 # When the state is modified reset dirty status and emit the delta to the frontend.
                 state._clean()

+ 22 - 30
reflex/app_mixins/middleware.py

@@ -2,8 +2,8 @@
 
 from __future__ import annotations
 
-import asyncio
 import dataclasses
+import inspect
 
 from reflex.event import Event
 from reflex.middleware import HydrateMiddleware, Middleware
@@ -16,11 +16,11 @@ from .mixin import AppMixin
 class MiddlewareMixin(AppMixin):
     """Middleware Mixin that allow to add middleware to the app."""
 
-    # Middleware to add to the app. Users should use `add_middleware`. PRIVATE.
-    middleware: list[Middleware] = dataclasses.field(default_factory=list)
+    # Middleware to add to the app. Users should use `add_middleware`.
+    _middlewares: list[Middleware] = dataclasses.field(default_factory=list)
 
     def _init_mixin(self):
-        self.middleware.append(HydrateMiddleware())
+        self._middlewares.append(HydrateMiddleware())
 
     def add_middleware(self, middleware: Middleware, index: int | None = None):
         """Add middleware to the app.
@@ -30,9 +30,9 @@ class MiddlewareMixin(AppMixin):
             index: The index to add the middleware at.
         """
         if index is None:
-            self.middleware.append(middleware)
+            self._middlewares.append(middleware)
         else:
-            self.middleware.insert(index, middleware)
+            self._middlewares.insert(index, middleware)
 
     async def _preprocess(self, state: BaseState, event: Event) -> StateUpdate | None:
         """Preprocess the event.
@@ -50,13 +50,12 @@ class MiddlewareMixin(AppMixin):
         Returns:
             An optional state to return.
         """
-        for middleware in self.middleware:
-            if asyncio.iscoroutinefunction(middleware.preprocess):
-                out = await middleware.preprocess(app=self, state=state, event=event)  # pyright: ignore [reportArgumentType]
-            else:
-                out = middleware.preprocess(app=self, state=state, event=event)  # pyright: ignore [reportArgumentType]
+        for middleware in self._middlewares:
+            out = middleware.preprocess(app=self, state=state, event=event)  # pyright: ignore [reportArgumentType]
+            if inspect.isawaitable(out):
+                out = await out
             if out is not None:
-                return out  # pyright: ignore [reportReturnType]
+                return out
 
     async def _postprocess(
         self, state: BaseState, event: Event, update: StateUpdate
@@ -74,21 +73,14 @@ class MiddlewareMixin(AppMixin):
         Returns:
             The state update to return.
         """
-        for middleware in self.middleware:
-            if asyncio.iscoroutinefunction(middleware.postprocess):
-                out = await middleware.postprocess(
-                    app=self,  # pyright: ignore [reportArgumentType]
-                    state=state,
-                    event=event,
-                    update=update,
-                )
-            else:
-                out = middleware.postprocess(
-                    app=self,  # pyright: ignore [reportArgumentType]
-                    state=state,
-                    event=event,
-                    update=update,
-                )
-            if out is not None:
-                return out  # pyright: ignore [reportReturnType]
-        return update
+        out = update
+        for middleware in self._middlewares:
+            out = middleware.postprocess(
+                app=self,  # pyright: ignore [reportArgumentType]
+                state=state,
+                event=event,
+                update=update,
+            )
+            if inspect.isawaitable(out):
+                out = await out
+        return out  # pyright: ignore[reportReturnType]

+ 0 - 33
reflex/app_module_for_backend.py

@@ -1,33 +0,0 @@
-"""Shims the real reflex app module for running backend server (uvicorn or gunicorn).
-Only the app attribute is explicitly exposed.
-"""
-
-from concurrent.futures import ThreadPoolExecutor
-
-from reflex import constants
-from reflex.utils.exec import is_prod_mode
-from reflex.utils.prerequisites import get_and_validate_app
-
-if constants.CompileVars.APP != "app":
-    raise AssertionError("unexpected variable name for 'app'")
-
-app, app_module = get_and_validate_app(reload=False)
-# For py3.9 compatibility when redis is used, we MUST add any decorator pages
-# before compiling the app in a thread to avoid event loop error (REF-2172).
-app._apply_decorated_pages()
-compile_future = ThreadPoolExecutor(max_workers=1).submit(app._compile)
-compile_future.add_done_callback(
-    # Force background compile errors to print eagerly
-    lambda f: f.result()
-)
-# Wait for the compile to finish in prod mode to ensure all optional endpoints are mounted.
-if is_prod_mode():
-    compile_future.result()
-
-# ensure only "app" is exposed.
-del app_module
-del compile_future
-del get_and_validate_app
-del is_prod_mode
-del constants
-del ThreadPoolExecutor

+ 3 - 3
reflex/base.py

@@ -38,7 +38,7 @@ 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  # pyright: ignore [reportPossiblyUnboundVariable, reportPrivateImportUsage]
+pydantic_main.validate_field_name = validate_field_name  # pyright: ignore [reportPrivateImportUsage]
 
 if TYPE_CHECKING:
     from reflex.vars import Var
@@ -107,7 +107,7 @@ class Base(BaseModel):
             default_value: The default value of the field
         """
         var_name = var._var_field_name
-        new_field = ModelField.infer(  # pyright: ignore [reportPossiblyUnboundVariable]
+        new_field = ModelField.infer(
             name=var_name,
             value=default_value,
             annotation=var._var_type,
@@ -128,5 +128,5 @@ class Base(BaseModel):
         if isinstance(key, str):
             # Seems like this function signature was wrong all along?
             # If the user wants a field that we know of, get it and pass it off to _get_value
-            return getattr(self, key, key)
+            return getattr(self, key)
         return key

+ 123 - 10
reflex/compiler/compiler.py

@@ -17,8 +17,11 @@ from reflex.components.component import (
     StatefulComponent,
 )
 from reflex.config import environment, get_config
+from reflex.constants.compiler import PageNames
 from reflex.state import BaseState
 from reflex.style import SYSTEM_COLOR_MODE
+from reflex.utils import console, path_ops
+from reflex.utils.exceptions import ReflexError
 from reflex.utils.exec import is_prod_mode
 from reflex.utils.imports import ImportVar
 from reflex.utils.prerequisites import get_web_dir
@@ -172,6 +175,42 @@ def compile_root_stylesheet(stylesheets: list[str]) -> tuple[str, str]:
     return output_path, code
 
 
+def _validate_stylesheet(stylesheet_full_path: Path, assets_app_path: Path) -> None:
+    """Validate the stylesheet.
+
+    Args:
+        stylesheet_full_path: The stylesheet to validate.
+        assets_app_path: The path to the assets directory.
+
+    Raises:
+        ValueError: If the stylesheet is not supported.
+        FileNotFoundError: If the stylesheet is not found.
+    """
+    suffix = stylesheet_full_path.suffix[1:] if stylesheet_full_path.suffix else ""
+    if suffix not in constants.Reflex.STYLESHEETS_SUPPORTED:
+        raise ValueError(f"Stylesheet file {stylesheet_full_path} is not supported.")
+    if not stylesheet_full_path.absolute().is_relative_to(assets_app_path.absolute()):
+        raise FileNotFoundError(
+            f"Cannot include stylesheets from outside the assets directory: {stylesheet_full_path}"
+        )
+    if not stylesheet_full_path.name:
+        raise ValueError(
+            f"Stylesheet file name cannot be empty: {stylesheet_full_path}"
+        )
+    if (
+        len(
+            stylesheet_full_path.absolute()
+            .relative_to(assets_app_path.absolute())
+            .parts
+        )
+        == 1
+        and stylesheet_full_path.stem == PageNames.STYLESHEET_ROOT
+    ):
+        raise ValueError(
+            f"Stylesheet file name cannot be '{PageNames.STYLESHEET_ROOT}': {stylesheet_full_path}"
+        )
+
+
 def _compile_root_stylesheet(stylesheets: list[str]) -> str:
     """Compile the root stylesheet.
 
@@ -190,18 +229,75 @@ def _compile_root_stylesheet(stylesheets: list[str]) -> str:
         if get_config().tailwind is not None
         else []
     )
+
+    failed_to_import_sass = False
+    assets_app_path = Path.cwd() / constants.Dirs.APP_ASSETS
+
+    stylesheets_files: list[Path] = []
+    stylesheets_urls = []
+
     for stylesheet in stylesheets:
         if not utils.is_valid_url(stylesheet):
             # check if stylesheet provided exists.
-            stylesheet_full_path = (
-                Path.cwd() / constants.Dirs.APP_ASSETS / stylesheet.strip("/")
-            )
+            stylesheet_full_path = assets_app_path / stylesheet.strip("/")
+
             if not stylesheet_full_path.exists():
                 raise FileNotFoundError(
                     f"The stylesheet file {stylesheet_full_path} does not exist."
                 )
-            stylesheet = f"../{constants.Dirs.PUBLIC}/{stylesheet.strip('/')}"
-        sheets.append(stylesheet) if stylesheet not in sheets else None
+
+            if stylesheet_full_path.is_dir():
+                all_files = (
+                    file
+                    for ext in constants.Reflex.STYLESHEETS_SUPPORTED
+                    for file in stylesheet_full_path.rglob("*." + ext)
+                )
+                for file in all_files:
+                    if file.is_dir():
+                        continue
+                    # Validate the stylesheet.
+                    _validate_stylesheet(file, assets_app_path)
+                    stylesheets_files.append(file)
+
+            else:
+                # Validate the stylesheet.
+                _validate_stylesheet(stylesheet_full_path, assets_app_path)
+                stylesheets_files.append(stylesheet_full_path)
+        else:
+            stylesheets_urls.append(stylesheet)
+
+    sheets.extend(dict.fromkeys(stylesheets_urls))
+
+    for stylesheet in stylesheets_files:
+        target_path = stylesheet.relative_to(assets_app_path).with_suffix(".css")
+        target = get_web_dir() / constants.Dirs.STYLES / target_path
+
+        target.parent.mkdir(parents=True, exist_ok=True)
+
+        if stylesheet.suffix == ".css":
+            path_ops.cp(src=stylesheet, dest=target, overwrite=True)
+        else:
+            try:
+                from sass import compile as sass_compile
+
+                target.write_text(
+                    data=sass_compile(
+                        filename=str(stylesheet),
+                        output_style="compressed",
+                    ),
+                    encoding="utf8",
+                )
+            except ImportError:
+                failed_to_import_sass = True
+
+        str_target_path = "./" + str(target_path)
+        sheets.append(str_target_path) if str_target_path not in sheets else None
+
+    if failed_to_import_sass:
+        console.error(
+            'The `libsass` package is required to compile sass/scss stylesheet files. Run `pip install "libsass>=0.23.0"`.'
+        )
+
     return templates.STYLE.render(stylesheets=sheets)
 
 
@@ -247,12 +343,19 @@ def _compile_components(
         for comp_import in comp_render["dynamic_imports"]
     }
 
+    custom_codes = {
+        comp_custom_code: None
+        for comp_render in component_renders
+        for comp_custom_code in comp_render.get("custom_code", [])
+    }
+
     # Compile the components page.
     return (
         templates.COMPONENTS.render(
             imports=utils.compile_imports(imports),
             components=component_renders,
             dynamic_imports=dynamic_imports,
+            custom_codes=custom_codes,
         ),
         imports,
     )
@@ -304,13 +407,11 @@ def _compile_stateful_components(
 
             # Include dynamic imports in the shared component.
             if dynamic_imports := component._get_all_dynamic_imports():
-                rendered_components.update(
-                    {dynamic_import: None for dynamic_import in dynamic_imports}
-                )
+                rendered_components.update(dict.fromkeys(dynamic_imports))
 
             # Include custom code in the shared component.
             rendered_components.update(
-                {code: None for code in component._get_all_custom_code()},
+                dict.fromkeys(component._get_all_custom_code()),
             )
 
             # Include all imports in the shared component.
@@ -548,7 +649,15 @@ if TYPE_CHECKING:
     from reflex.app import ComponentCallable, UnevaluatedPage
 
 
-def _into_component_once(component: Component | ComponentCallable) -> Component | None:
+def _into_component_once(
+    component: Component
+    | ComponentCallable
+    | tuple[Component, ...]
+    | str
+    | Var
+    | int
+    | float,
+) -> Component | None:
     """Convert a component to a Component.
 
     Args:
@@ -589,6 +698,8 @@ def into_component(component: Component | ComponentCallable) -> Component:
         ):
             return converted
     except KeyError as e:
+        if isinstance(e, ReflexError):
+            raise
         key = e.args[0] if e.args else None
         if key is not None and isinstance(key, Var):
             raise TypeError(
@@ -596,6 +707,8 @@ def into_component(component: Component | ComponentCallable) -> Component:
             ).with_traceback(e.__traceback__) from None
         raise
     except TypeError as e:
+        if isinstance(e, ReflexError):
+            raise
         message = e.args[0] if e.args else None
         if message and isinstance(message, str):
             if message.endswith("has no len()") and (

+ 4 - 4
reflex/compiler/utils.py

@@ -7,7 +7,7 @@ import concurrent.futures
 import traceback
 from datetime import datetime
 from pathlib import Path
-from typing import Any, Callable, Type
+from typing import Any, Sequence, Type
 from urllib.parse import urlparse
 
 from pydantic.v1.fields import ModelField
@@ -318,7 +318,7 @@ def compile_custom_component(
     }
 
     # Concatenate the props.
-    props = [prop._js_expr for prop in component.get_prop_vars()]
+    props = list(component.props)
 
     # Compile the component.
     return (
@@ -335,7 +335,7 @@ def compile_custom_component(
 
 
 def create_document_root(
-    head_components: list[Component] | None = None,
+    head_components: Sequence[Component] | None = None,
     html_lang: str | None = None,
     html_custom_attrs: dict[str, Var | str] | None = None,
 ) -> Component:
@@ -371,7 +371,7 @@ def create_theme(style: ComponentStyle) -> dict:
         The base style for the app.
     """
     # Get the global style from the style dict.
-    style_rules = Style({k: v for k, v in style.items() if not isinstance(k, Callable)})
+    style_rules = Style({k: v for k, v in style.items() if isinstance(k, str)})
 
     root_style = {
         # Root styles.

+ 0 - 23
reflex/components/__init__.pyi

@@ -1,23 +0,0 @@
-"""Stub file for reflex/components/__init__.py"""
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-
-from . import base as base
-from . import core as core
-from . import datadisplay as datadisplay
-from . import el as el
-from . import gridjs as gridjs
-from . import lucide as lucide
-from . import markdown as markdown
-from . import moment as moment
-from . import plotly as plotly
-from . import radix as radix
-from . import react_player as react_player
-from . import recharts as recharts
-from . import sonner as sonner
-from . import suneditor as suneditor
-from .component import Component as Component
-from .component import NoSSRComponent as NoSSRComponent
-from .next import NextLink as NextLink
-from .next import next_link as next_link

+ 0 - 26
reflex/components/base/__init__.pyi

@@ -1,26 +0,0 @@
-"""Stub file for reflex/components/base/__init__.py"""
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-
-from . import app_wrap as app_wrap
-from . import bare as bare
-from .body import Body as Body
-from .document import DocumentHead as DocumentHead
-from .document import Html as Html
-from .document import Main as Main
-from .document import NextScript as NextScript
-from .error_boundary import ErrorBoundary as ErrorBoundary
-from .error_boundary import error_boundary as error_boundary
-from .fragment import Fragment as Fragment
-from .fragment import fragment as fragment
-from .head import Head as Head
-from .head import head as head
-from .link import RawLink as RawLink
-from .link import ScriptTag as ScriptTag
-from .meta import Description as Description
-from .meta import Image as Image
-from .meta import Meta as Meta
-from .meta import Title as Title
-from .script import Script as Script
-from .script import script as script

+ 0 - 47
reflex/components/base/app_wrap.pyi

@@ -1,47 +0,0 @@
-"""Stub file for reflex/components/base/app_wrap.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, overload
-
-from reflex.components.base.fragment import Fragment
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-class AppWrap(Fragment):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "AppWrap":
-        """Create a new AppWrap component.
-
-        Returns:
-            A new AppWrap component containing {children}.
-        """
-        ...

+ 3 - 3
reflex/components/base/bare.py

@@ -70,13 +70,13 @@ class Bare(Component):
         if isinstance(contents, Var):
             if isinstance(contents, LiteralStringVar):
                 validate_str(contents._var_value)
-            return cls(contents=contents)
+            return cls._unsafe_create(children=[], contents=contents)
         else:
             if isinstance(contents, str):
                 validate_str(contents)
-            contents = str(contents) if contents is not None else ""
+            contents = Var.create(contents if contents is not None else "")
 
-        return cls(contents=contents)
+        return cls._unsafe_create(children=[], contents=contents)
 
     def _get_all_hooks_internal(self) -> dict[str, VarData | None]:
         """Include the hooks for the component.

+ 0 - 57
reflex/components/base/body.pyi

@@ -1,57 +0,0 @@
-"""Stub file for reflex/components/base/body.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, overload
-
-from reflex.components.component import Component
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-class Body(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Body":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...

+ 0 - 242
reflex/components/base/document.pyi

@@ -1,242 +0,0 @@
-"""Stub file for reflex/components/base/document.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, overload
-
-from reflex.components.component import Component
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-class NextDocumentLib(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "NextDocumentLib":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-class Html(NextDocumentLib):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        lang: str | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Html":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-class DocumentHead(NextDocumentLib):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "DocumentHead":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-class Main(NextDocumentLib):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Main":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-class NextScript(NextDocumentLib):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "NextScript":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...

+ 0 - 68
reflex/components/base/error_boundary.pyi

@@ -1,68 +0,0 @@
-"""Stub file for reflex/components/base/error_boundary.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, overload
-
-from reflex.components.component import Component
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-from reflex.vars.object import ObjectVar
-
-def on_error_spec(
-    error: ObjectVar[dict[str, str]], info: ObjectVar[dict[str, str]]
-) -> tuple[Var[str], Var[str]]: ...
-
-class ErrorBoundary(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        fallback_render: Component | Var[Component] | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_error: Optional[EventType[()] | EventType[str] | EventType[str, str]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "ErrorBoundary":
-        """Create an ErrorBoundary component.
-
-        Args:
-            *children: The children of the component.
-            on_error: Fired when the boundary catches an error.
-            fallback_render: Rendered instead of the children when an error is caught.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The ErrorBoundary component.
-        """
-        ...
-
-error_boundary = ErrorBoundary.create

+ 0 - 59
reflex/components/base/fragment.pyi

@@ -1,59 +0,0 @@
-"""Stub file for reflex/components/base/fragment.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, overload
-
-from reflex.components.component import Component
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-class Fragment(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Fragment":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-fragment = Fragment.create

+ 0 - 105
reflex/components/base/head.pyi

@@ -1,105 +0,0 @@
-"""Stub file for reflex/components/base/head.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, overload
-
-from reflex.components.component import Component, MemoizationLeaf
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-class NextHeadLib(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "NextHeadLib":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-class Head(NextHeadLib, MemoizationLeaf):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Head":
-        """Create a new memoization leaf component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The memoization leaf
-        """
-        ...
-
-head = Head.create

+ 0 - 121
reflex/components/base/link.pyi

@@ -1,121 +0,0 @@
-"""Stub file for reflex/components/base/link.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, overload
-
-from reflex.components.component import Component
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-class RawLink(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        href: Var[str] | str | None = None,
-        rel: Var[str] | str | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "RawLink":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            href: The href.
-            rel: The type of link.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-class ScriptTag(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        type_: Var[str] | str | None = None,
-        source: Var[str] | str | None = None,
-        integrity: Var[str] | str | None = None,
-        crossorigin: Var[str] | str | None = None,
-        referrer_policy: Var[str] | str | None = None,
-        is_async: Var[bool] | bool | None = None,
-        defer: Var[bool] | bool | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "ScriptTag":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            type_: The type of script represented.
-            source: The URI of an external script.
-            integrity: Metadata to verify the content of the script.
-            crossorigin: Whether to allow cross-origin requests.
-            referrer_policy: Indicates which referrer to send when fetching the script.
-            is_async: Whether to asynchronously load the script.
-            defer: Whether to defer loading the script.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...

+ 0 - 226
reflex/components/base/meta.pyi

@@ -1,226 +0,0 @@
-"""Stub file for reflex/components/base/meta.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, overload
-
-from reflex.components.component import Component
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-class Title(Component):
-    def render(self) -> dict: ...
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Title":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-class Meta(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        char_set: str | None = None,
-        content: str | None = None,
-        name: str | None = None,
-        property: str | None = None,
-        http_equiv: str | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Meta":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            char_set: The description of character encoding.
-            content: The value of meta.
-            name: The name of metadata.
-            property: The type of metadata value.
-            http_equiv: The type of metadata value.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-class Description(Meta):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        name: str | None = None,
-        char_set: str | None = None,
-        content: str | None = None,
-        property: str | None = None,
-        http_equiv: str | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Description":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            name: The name of metadata.
-            char_set: The description of character encoding.
-            content: The value of meta.
-            property: The type of metadata value.
-            http_equiv: The type of metadata value.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-class Image(Meta):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        property: str | None = None,
-        char_set: str | None = None,
-        content: str | None = None,
-        name: str | None = None,
-        http_equiv: str | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Image":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            property: The type of metadata value.
-            char_set: The description of character encoding.
-            content: The value of meta.
-            name: The name of metadata.
-            http_equiv: The type of metadata value.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...

+ 0 - 84
reflex/components/base/script.pyi

@@ -1,84 +0,0 @@
-"""Stub file for reflex/components/base/script.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Literal, Optional, overload
-
-from reflex.components.component import Component
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-class Script(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        src: Var[str] | str | None = None,
-        strategy: Literal["afterInteractive", "beforeInteractive", "lazyOnload"]
-        | Var[Literal["afterInteractive", "beforeInteractive", "lazyOnload"]]
-        | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_error: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_load: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_ready: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Script":
-        """Create an inline or user-defined script.
-
-        If a string is provided as the first child, it will be rendered as an inline script
-        otherwise the `src` prop must be provided.
-
-        The following event triggers are provided:
-
-        on_load: Execute code after the script has finished loading.
-        on_ready: Execute code after the script has finished loading and every
-            time the component is mounted.
-        on_error: Execute code if the script fails to load.
-
-        Args:
-            *children: The children of the component.
-            src: Required unless inline script is used
-            strategy: When the script will execute: afterInteractive (defer-like behavior) | beforeInteractive | lazyOnload (async-like behavior)
-            on_load: Triggered when the script is loading
-            on_ready: Triggered when the script has loaded
-            on_error: Triggered when the script has errored
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-
-        Raises:
-            ValueError: when neither children nor `src` are specified.
-        """
-        ...
-
-script = Script.create

+ 0 - 57
reflex/components/base/strict_mode.pyi

@@ -1,57 +0,0 @@
-"""Stub file for reflex/components/base/strict_mode.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, overload
-
-from reflex.components.component import Component
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-class StrictMode(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "StrictMode":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...

+ 243 - 119
reflex/components/component.py

@@ -2,8 +2,10 @@
 
 from __future__ import annotations
 
+import contextlib
 import copy
 import dataclasses
+import functools
 import inspect
 import typing
 from abc import ABC, abstractmethod
@@ -16,15 +18,19 @@ from typing import (
     ClassVar,
     Iterator,
     List,
+    Mapping,
     Sequence,
     Set,
     Type,
+    TypeVar,
     Union,
+    cast,
     get_args,
     get_origin,
 )
 
-from typing_extensions import Self
+import pydantic.v1
+from rich.markup import escape
 
 import reflex.state
 from reflex.base import Base
@@ -44,15 +50,16 @@ from reflex.constants import (
 from reflex.constants.compiler import SpecialAttributes
 from reflex.constants.state import FRONTEND_EVENT_STATE
 from reflex.event import (
-    EventActionsMixin,
     EventCallback,
     EventChain,
     EventHandler,
     EventSpec,
     no_args_event_spec,
+    parse_args_spec,
+    run_script,
 )
 from reflex.style import Style, format_as_emotion
-from reflex.utils import format, imports, types
+from reflex.utils import console, format, imports, types
 from reflex.utils.imports import ImportDict, ImportVar, ParsedImportDict, parse_imports
 from reflex.vars import VarData
 from reflex.vars.base import (
@@ -61,7 +68,7 @@ from reflex.vars.base import (
     Var,
     cached_property_no_lock,
 )
-from reflex.vars.function import ArgsFunctionOperation, FunctionStringVar
+from reflex.vars.function import ArgsFunctionOperation, FunctionStringVar, FunctionVar
 from reflex.vars.number import ternary_operation
 from reflex.vars.object import ObjectVar
 from reflex.vars.sequence import LiteralArrayVar
@@ -74,19 +81,19 @@ class BaseComponent(Base, ABC):
     """
 
     # The children nested within the component.
-    children: list[BaseComponent] = []
+    children: list[BaseComponent] = pydantic.v1.Field(default_factory=list)
 
     # The library that the component is based on.
-    library: str | None = None
+    library: str | None = pydantic.v1.Field(default_factory=lambda: None)
 
     # List here the non-react dependency needed by `library`
-    lib_dependencies: list[str] = []
+    lib_dependencies: list[str] = pydantic.v1.Field(default_factory=list)
 
     # List here the dependencies that need to be transpiled by Next.js
-    transpile_packages: list[str] = []
+    transpile_packages: list[str] = pydantic.v1.Field(default_factory=list)
 
     # The tag to use when rendering the component.
-    tag: str | None = None
+    tag: str | None = pydantic.v1.Field(default_factory=lambda: None)
 
     @abstractmethod
     def render(self) -> dict:
@@ -175,7 +182,19 @@ def evaluate_style_namespaces(style: ComponentStyle) -> dict:
 # Map from component to styling.
 ComponentStyle = dict[str | Type[BaseComponent] | Callable | ComponentNamespace, Any]
 ComponentChild = types.PrimitiveType | Var | BaseComponent
-ComponentChildTypes = (*types.PrimitiveTypes, Var, BaseComponent)
+ComponentChildTypes = (*types.PrimitiveTypes, Var, BaseComponent, type(None))
+
+
+def _satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
+    return types._isinstance(
+        obj,
+        type_hint,
+        nested=1,
+        treat_var_as_type=True,
+        treat_mutable_obj_as_immutable=(
+            isinstance(obj, Var) and not isinstance(obj, LiteralVar)
+        ),
+    )
 
 
 def satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
@@ -188,7 +207,23 @@ def satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
     Returns:
         Whether the object satisfies the type hint.
     """
-    return types._isinstance(obj, type_hint, nested=1)
+    if _satisfies_type_hint(obj, type_hint):
+        return True
+    if _satisfies_type_hint(obj, type_hint | None):
+        obj = (
+            obj
+            if not isinstance(obj, Var)
+            else (obj._var_value if isinstance(obj, LiteralVar) else obj)
+        )
+        console.deprecate(
+            "implicit-none-for-component-fields",
+            reason="Passing Vars with possible None values to component fields not explicitly marked as Optional is deprecated. "
+            + f"Passed {obj!s} of type {escape(str(type(obj) if not isinstance(obj, Var) else obj._var_type))} to {escape(str(type_hint))}.",
+            deprecation_version="0.7.2",
+            removal_version="0.8.0",
+        )
+        return True
+    return False
 
 
 def _components_from(
@@ -210,56 +245,81 @@ def _components_from(
     return ()
 
 
+DEFAULT_TRIGGERS: dict[str, types.ArgsSpec | Sequence[types.ArgsSpec]] = {
+    EventTriggers.ON_FOCUS: no_args_event_spec,
+    EventTriggers.ON_BLUR: no_args_event_spec,
+    EventTriggers.ON_CLICK: no_args_event_spec,
+    EventTriggers.ON_CONTEXT_MENU: no_args_event_spec,
+    EventTriggers.ON_DOUBLE_CLICK: no_args_event_spec,
+    EventTriggers.ON_MOUSE_DOWN: no_args_event_spec,
+    EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
+    EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
+    EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
+    EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
+    EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
+    EventTriggers.ON_MOUSE_UP: no_args_event_spec,
+    EventTriggers.ON_SCROLL: no_args_event_spec,
+    EventTriggers.ON_MOUNT: no_args_event_spec,
+    EventTriggers.ON_UNMOUNT: no_args_event_spec,
+}
+
+T = TypeVar("T", bound="Component")
+
+
 class Component(BaseComponent, ABC):
     """A component with style, event trigger and other props."""
 
     # The style of the component.
-    style: Style = Style()
+    style: Style = pydantic.v1.Field(default_factory=Style)
 
     # A mapping from event triggers to event chains.
-    event_triggers: dict[str, EventChain | Var] = {}
+    event_triggers: dict[str, EventChain | Var] = pydantic.v1.Field(
+        default_factory=dict
+    )
 
     # The alias for the tag.
-    alias: str | None = None
+    alias: str | None = pydantic.v1.Field(default_factory=lambda: None)
 
     # Whether the import is default or named.
-    is_default: bool | None = False
+    is_default: bool | None = pydantic.v1.Field(default_factory=lambda: False)
 
     # A unique key for the component.
-    key: Any = None
+    key: Any = pydantic.v1.Field(default_factory=lambda: None)
 
     # The id for the component.
-    id: Any = None
+    id: Any = pydantic.v1.Field(default_factory=lambda: None)
 
     # The class name for the component.
-    class_name: Any = None
+    class_name: Any = pydantic.v1.Field(default_factory=lambda: None)
 
     # Special component props.
-    special_props: list[Var] = []
+    special_props: list[Var] = pydantic.v1.Field(default_factory=list)
 
     # Whether the component should take the focus once the page is loaded
-    autofocus: bool = False
+    autofocus: bool = pydantic.v1.Field(default_factory=lambda: False)
 
     # components that cannot be children
-    _invalid_children: list[str] = []
+    _invalid_children: ClassVar[list[str]] = []
 
     # only components that are allowed as children
-    _valid_children: list[str] = []
+    _valid_children: ClassVar[list[str]] = []
 
     # only components that are allowed as parent
-    _valid_parents: list[str] = []
+    _valid_parents: ClassVar[list[str]] = []
 
     # props to change the name of
-    _rename_props: dict[str, str] = {}
+    _rename_props: ClassVar[dict[str, str]] = {}
 
     # custom attribute
-    custom_attrs: dict[str, Var | Any] = {}
+    custom_attrs: dict[str, Var | Any] = pydantic.v1.Field(default_factory=dict)
 
     # When to memoize this component and its children.
     _memoization_mode: MemoizationMode = MemoizationMode()
 
     # State class associated with this component instance
-    State: Type[reflex.state.State] | None = None
+    State: Type[reflex.state.State] | None = pydantic.v1.Field(
+        default_factory=lambda: None
+    )
 
     def add_imports(self) -> ImportDict | list[ImportDict]:
         """Add imports for the component.
@@ -365,11 +425,13 @@ class Component(BaseComponent, ABC):
                 continue
 
             # Set default values for any props.
-            if types._issubclass(field.type_, Var):
+            if field.type_ is Var:
                 field.required = False
                 if field.default is not None:
-                    field.default = LiteralVar.create(field.default)
-            elif types._issubclass(field.type_, EventHandler):
+                    field.default_factory = functools.partial(
+                        LiteralVar.create, field.default
+                    )
+            elif field.type_ is EventHandler:
                 field.required = False
 
         # Ensure renamed props from parent classes are applied to the subclass.
@@ -380,7 +442,24 @@ class Component(BaseComponent, ABC):
                     inherited_rename_props.update(parent._rename_props)
             cls._rename_props = inherited_rename_props
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, **kwargs):
+        """Initialize the custom component.
+
+        Args:
+            **kwargs: The kwargs to pass to the component.
+        """
+        console.deprecate(
+            "component-direct-instantiation",
+            reason="Use the `create` method instead.",
+            deprecation_version="0.7.2",
+            removal_version="0.8.0",
+        )
+        super().__init__(
+            children=kwargs.get("children", []),
+        )
+        self._post_init(**kwargs)
+
+    def _post_init(self, *args, **kwargs):
         """Initialize the component.
 
         Args:
@@ -393,16 +472,6 @@ class Component(BaseComponent, ABC):
         """
         # Set the id and children initially.
         children = kwargs.get("children", [])
-        initial_kwargs = {
-            "id": kwargs.get("id"),
-            "children": children,
-            **{
-                prop: LiteralVar.create(kwargs[prop])
-                for prop in self.get_initial_props()
-                if prop in kwargs
-            },
-        }
-        super().__init__(**initial_kwargs)
 
         self._validate_component_children(children)
 
@@ -430,11 +499,10 @@ class Component(BaseComponent, ABC):
                 )
             if key in component_specific_triggers:
                 # Event triggers are bound to event chains.
-                field_type = EventChain
+                is_var = False
             elif key in props:
                 # Set the field type.
-                field_type = fields[key].type_
-
+                is_var = field.type_ is Var if (field := fields.get(key)) else False
             else:
                 continue
 
@@ -449,13 +517,14 @@ class Component(BaseComponent, ABC):
                 return key
 
             # Check whether the key is a component prop.
-            if types._issubclass(field_type, Var):
-                # Used to store the passed types if var type is a union.
-                passed_types = None
+            if is_var:
                 try:
                     kwargs[key] = determine_key(value)
 
-                    expected_type = fields[key].outer_type_.__args__[0]
+                    expected_type = types.get_args(
+                        types.get_field_type(type(self), key)
+                    )[0]
+
                     # validate literal fields.
                     types.validate_literal(
                         key, value, expected_type, type(self).__name__
@@ -470,22 +539,9 @@ class Component(BaseComponent, ABC):
                 except TypeError:
                     # If it is not a valid var, check the base types.
                     passed_type = type(value)
-                    expected_type = fields[key].outer_type_
-                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__ if arg is not type(None)
-                    )
-                if (
-                    # If the passed var is a union, check if all possible types are valid.
-                    passed_types
-                    and not all(
-                        types._issubclass(pt, expected_type) for pt in passed_types
-                    )
-                ) or (
-                    # Else just check if the passed var type is valid.
-                    not passed_types and not satisfies_type_hint(value, expected_type)
-                ):
+                    expected_type = types.get_field_type(type(self), key)
+
+                if not satisfies_type_hint(value, expected_type):
                     value_name = value._js_expr if isinstance(value, Var) else value
 
                     additional_info = (
@@ -523,9 +579,15 @@ class Component(BaseComponent, ABC):
 
         # Add style props to the component.
         style = kwargs.get("style", {})
-        if isinstance(style, List):
+        if isinstance(style, Sequence):
+            if any(not isinstance(s, Mapping) for s in style):
+                raise TypeError("Style must be a dictionary or a list of dictionaries.")
             # Merge styles, the later ones overriding keys in the earlier ones.
-            style = {k: v for style_dict in style for k, v in style_dict.items()}
+            style = {
+                k: v
+                for style_dict in style
+                for k, v in cast(Mapping, style_dict).items()
+            }
 
         if isinstance(style, (Breakpoints, Var)):
             style = {
@@ -533,9 +595,15 @@ class Component(BaseComponent, ABC):
                 "&": style,
             }
 
+        fields_style = self.get_fields()["style"]
+
         kwargs["style"] = Style(
             {
-                **self.get_fields()["style"].default,
+                **(
+                    fields_style.default_factory()
+                    if fields_style.default_factory
+                    else fields_style.default
+                ),
                 **style,
                 **{attr: value for attr, value in kwargs.items() if attr not in fields},
             }
@@ -552,7 +620,8 @@ class Component(BaseComponent, ABC):
                 kwargs["class_name"] = " ".join(class_name)
 
         # Construct the component.
-        super().__init__(*args, **kwargs)
+        for key, value in kwargs.items():
+            setattr(self, key, value)
 
     def get_event_triggers(
         self,
@@ -562,34 +631,17 @@ class Component(BaseComponent, ABC):
         Returns:
             The event triggers.
         """
-        default_triggers: dict[str, types.ArgsSpec | Sequence[types.ArgsSpec]] = {
-            EventTriggers.ON_FOCUS: no_args_event_spec,
-            EventTriggers.ON_BLUR: no_args_event_spec,
-            EventTriggers.ON_CLICK: no_args_event_spec,
-            EventTriggers.ON_CONTEXT_MENU: no_args_event_spec,
-            EventTriggers.ON_DOUBLE_CLICK: no_args_event_spec,
-            EventTriggers.ON_MOUSE_DOWN: no_args_event_spec,
-            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
-            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
-            EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
-            EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
-            EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
-            EventTriggers.ON_MOUSE_UP: no_args_event_spec,
-            EventTriggers.ON_SCROLL: no_args_event_spec,
-            EventTriggers.ON_MOUNT: no_args_event_spec,
-            EventTriggers.ON_UNMOUNT: no_args_event_spec,
-        }
-
+        triggers = DEFAULT_TRIGGERS.copy()
         # Look for component specific triggers,
         # e.g. variable declared as EventHandler types.
         for field in self.get_fields().values():
-            if types._issubclass(field.outer_type_, EventHandler):
+            if field.type_ is EventHandler:
                 args_spec = None
                 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)
-        return default_triggers
+                triggers[field.name] = args_spec or (no_args_event_spec)
+        return triggers
 
     def __repr__(self) -> str:
         """Represent the component in React.
@@ -703,9 +755,11 @@ class Component(BaseComponent, ABC):
         """
         return {
             name
-            for name, field in cls.get_fields().items()
+            for name in cls.get_fields()
             if name in cls.get_props()
-            and types._issubclass(field.outer_type_, Component)
+            and types._issubclass(
+                types.value_inside_optional(types.get_field_type(cls, name)), Component
+            )
         }
 
     def _get_components_in_props(self) -> Sequence[BaseComponent]:
@@ -729,7 +783,7 @@ class Component(BaseComponent, ABC):
         ]
 
     @classmethod
-    def create(cls, *children, **props) -> Self:
+    def create(cls: Type[T], *children, **props) -> T:
         """Create the component.
 
         Args:
@@ -761,7 +815,7 @@ class Component(BaseComponent, ABC):
         # Validate all the children.
         validate_children(children)
 
-        children = [
+        children_normalized = [
             (
                 child
                 if isinstance(child, Component)
@@ -774,7 +828,40 @@ class Component(BaseComponent, ABC):
             for child in children
         ]
 
-        return cls(children=children, **props)
+        return cls._create(children_normalized, **props)
+
+    @classmethod
+    def _create(cls: Type[T], children: Sequence[BaseComponent], **props: Any) -> T:
+        """Create the component.
+
+        Args:
+            children: The children of the component.
+            **props: The props of the component.
+
+        Returns:
+            The component.
+        """
+        comp = cls.construct(id=props.get("id"), children=list(children))
+        comp._post_init(children=list(children), **props)
+        return comp
+
+    @classmethod
+    def _unsafe_create(
+        cls: Type[T], children: Sequence[BaseComponent], **props: Any
+    ) -> T:
+        """Create the component without running post_init.
+
+        Args:
+            children: The children of the component.
+            **props: The props of the component.
+
+        Returns:
+            The component.
+        """
+        comp = cls.construct(id=props.get("id"), children=list(children))
+        for prop, value in props.items():
+            setattr(comp, prop, value)
+        return comp
 
     def add_style(self) -> dict[str, Any] | None:
         """Add style to the component.
@@ -808,7 +895,7 @@ class Component(BaseComponent, ABC):
             _style.update(s)
         return _style
 
-    def _get_component_style(self, styles: ComponentStyle) -> Style | None:
+    def _get_component_style(self, styles: ComponentStyle | Style) -> Style | None:
         """Get the style to the component from `App.style`.
 
         Args:
@@ -818,14 +905,14 @@ class Component(BaseComponent, ABC):
             The style of the component.
         """
         component_style = None
-        if type(self) in styles:
-            component_style = Style(styles[type(self)])
-        if self.create in styles:
-            component_style = Style(styles[self.create])
+        if (style := styles.get(type(self))) is not None:  # pyright: ignore [reportArgumentType]
+            component_style = Style(style)
+        if (style := styles.get(self.create)) is not None:  # pyright: ignore [reportArgumentType]
+            component_style = Style(style)
         return component_style
 
     def _add_style_recursive(
-        self, style: ComponentStyle, theme: Component | None = None
+        self, style: ComponentStyle | Style, theme: Component | None = None
     ) -> Component:
         """Add additional style to the component and its children.
 
@@ -958,8 +1045,8 @@ class Component(BaseComponent, ABC):
                     validate_child(c)
 
             if isinstance(child, Cond):
-                validate_child(child.comp1)
-                validate_child(child.comp2)
+                validate_child(child.children[0])
+                validate_child(child.children[1])
 
             if isinstance(child, Match):
                 for cases in child.match_cases:
@@ -1150,7 +1237,9 @@ class Component(BaseComponent, ABC):
         Yields:
             The parent classes that define the method (differently than the base).
         """
-        seen_methods = {getattr(Component, method)}
+        seen_methods = (
+            {getattr(Component, method)} if hasattr(Component, method) else set()
+        )
         for clz in cls.mro():
             if clz is Component:
                 break
@@ -1659,7 +1748,7 @@ class CustomComponent(Component):
     # The props of the component.
     props: dict[str, Any] = {}
 
-    def __init__(self, **kwargs):
+    def _post_init(self, **kwargs):
         """Initialize the custom component.
 
         Args:
@@ -1702,7 +1791,7 @@ class CustomComponent(Component):
                 )
             )
 
-        super().__init__(
+        super()._post_init(
             event_triggers={
                 key: EventChain.create(
                     value=props[key],
@@ -1736,7 +1825,7 @@ class CustomComponent(Component):
             type_ = props_types[key]
 
             # Handle event chains.
-            if types._issubclass(type_, EventActionsMixin):
+            if type_ is EventHandler:
                 inspect.getfullargspec(component_fn).annotations[key]
                 self.props[camel_cased_key] = EventChain.create(
                     value=value, args_spec=get_args_spec(key), key=key
@@ -1815,7 +1904,44 @@ class CustomComponent(Component):
 
         return custom_components
 
-    def get_prop_vars(self) -> List[Var]:
+    @staticmethod
+    def _get_event_spec_from_args_spec(name: str, event: EventChain) -> Callable:
+        """Get the event spec from the args spec.
+
+        Args:
+            name: The name of the event
+            event: The args spec.
+
+        Returns:
+            The event spec.
+        """
+
+        def fn(*args):
+            return run_script(Var(name).to(FunctionVar).call(*args))
+
+        if event.args_spec:
+            arg_spec = (
+                event.args_spec
+                if not isinstance(event.args_spec, Sequence)
+                else event.args_spec[0]
+            )
+            names = inspect.getfullargspec(arg_spec).args
+            fn.__signature__ = inspect.Signature(  # pyright: ignore[reportFunctionMemberAccess]
+                parameters=[
+                    inspect.Parameter(
+                        name=name,
+                        kind=inspect.Parameter.POSITIONAL_ONLY,
+                        annotation=arg._var_type,
+                    )
+                    for name, arg in zip(
+                        names, parse_args_spec(event.args_spec), strict=True
+                    )
+                ]
+            )
+
+        return fn
+
+    def get_prop_vars(self) -> List[Var | Callable]:
         """Get the prop vars.
 
         Returns:
@@ -1824,16 +1950,10 @@ class CustomComponent(Component):
         return [
             Var(
                 _js_expr=name,
-                _var_type=(
-                    prop._var_type
-                    if isinstance(prop, Var)
-                    else (
-                        type(prop)
-                        if not isinstance(prop, EventActionsMixin)
-                        else EventChain
-                    )
-                ),
+                _var_type=(prop._var_type if isinstance(prop, Var) else type(prop)),
             ).guess_type()
+            if isinstance(prop, Var) or not isinstance(prop, EventChain)
+            else CustomComponent._get_event_spec_from_args_spec(name, prop)
             for name, prop in self.props.items()
         ]
 
@@ -1863,7 +1983,9 @@ def custom_component(
     def wrapper(*children, **props) -> CustomComponent:
         # Remove the children from the props.
         props.pop("children", None)
-        return CustomComponent(component_fn=component_fn, children=children, **props)
+        return CustomComponent._create(
+            children=list(children), component_fn=component_fn, **props
+        )
 
     return wrapper
 
@@ -1895,13 +2017,15 @@ class NoSSRComponent(Component):
         # Do NOT import the main library/tag statically.
         import_name = self._get_import_name()
         if import_name is not None:
-            _imports[import_name] = [
+            with contextlib.suppress(ValueError):
+                _imports[import_name].remove(self.import_var)
+            _imports[import_name].append(
                 imports.ImportVar(
                     tag=None,
                     render=False,
                     transpile=self._should_transpile(self.library),
-                ),
-            ]
+                )
+            )
 
         return imports.merge_imports(
             dynamic_import,

+ 0 - 42
reflex/components/core/__init__.pyi

@@ -1,42 +0,0 @@
-"""Stub file for reflex/components/core/__init__.py"""
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-
-from . import layout as layout
-from .auto_scroll import auto_scroll as auto_scroll
-from .banner import ConnectionBanner as ConnectionBanner
-from .banner import ConnectionModal as ConnectionModal
-from .banner import ConnectionPulser as ConnectionPulser
-from .banner import ConnectionToaster as ConnectionToaster
-from .banner import connection_banner as connection_banner
-from .banner import connection_modal as connection_modal
-from .banner import connection_pulser as connection_pulser
-from .banner import connection_toaster as connection_toaster
-from .breakpoints import breakpoints as breakpoints
-from .breakpoints import set_breakpoints as set_breakpoints
-from .clipboard import Clipboard as Clipboard
-from .clipboard import clipboard as clipboard
-from .colors import color as color
-from .cond import Cond as Cond
-from .cond import color_mode_cond as color_mode_cond
-from .cond import cond as cond
-from .debounce import DebounceInput as DebounceInput
-from .debounce import debounce_input as debounce_input
-from .foreach import Foreach as Foreach
-from .foreach import foreach as foreach
-from .html import Html as Html
-from .html import html as html
-from .match import Match as Match
-from .match import match as match
-from .responsive import desktop_only as desktop_only
-from .responsive import mobile_and_tablet as mobile_and_tablet
-from .responsive import mobile_only as mobile_only
-from .responsive import tablet_and_desktop as tablet_and_desktop
-from .responsive import tablet_only as tablet_only
-from .upload import cancel_upload as cancel_upload
-from .upload import clear_selected_files as clear_selected_files
-from .upload import get_upload_dir as get_upload_dir
-from .upload import get_upload_url as get_upload_url
-from .upload import selected_files as selected_files
-from .upload import upload as upload

+ 8 - 1
reflex/components/core/auto_scroll.py

@@ -2,6 +2,8 @@
 
 from __future__ import annotations
 
+import dataclasses
+
 from reflex.components.el.elements.typography import Div
 from reflex.constants.compiler import MemoizationDisposition, MemoizationMode
 from reflex.utils.imports import ImportDict
@@ -28,7 +30,12 @@ class AutoScroll(Div):
         """
         props.setdefault("overflow", "auto")
         props.setdefault("id", get_unique_variable_name())
-        return super().create(*children, **props)
+        component = super().create(*children, **props)
+        if "key" in props:
+            component._memoization_mode = dataclasses.replace(
+                component._memoization_mode, recursive=True
+            )
+        return component
 
     def add_imports(self) -> ImportDict | list[ImportDict]:
         """Add imports required for the component.

+ 0 - 257
reflex/components/core/auto_scroll.pyi

@@ -1,257 +0,0 @@
-"""Stub file for reflex/components/core/auto_scroll.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Literal, Optional, overload
-
-from reflex.components.el.elements.typography import Div
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.utils.imports import ImportDict
-from reflex.vars.base import Var
-
-class AutoScroll(Div):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        access_key: Var[str] | str | None = None,
-        auto_capitalize: Literal[
-            "characters", "none", "off", "on", "sentences", "words"
-        ]
-        | Var[Literal["characters", "none", "off", "on", "sentences", "words"]]
-        | None = None,
-        content_editable: Literal["inherit", "plaintext-only", False, True]
-        | Var[Literal["inherit", "plaintext-only", False, True]]
-        | None = None,
-        context_menu: Var[str] | str | None = None,
-        dir: Var[str] | str | None = None,
-        draggable: Var[bool] | bool | None = None,
-        enter_key_hint: Literal[
-            "done", "enter", "go", "next", "previous", "search", "send"
-        ]
-        | Var[Literal["done", "enter", "go", "next", "previous", "search", "send"]]
-        | None = None,
-        hidden: Var[bool] | bool | None = None,
-        input_mode: Literal[
-            "decimal", "email", "none", "numeric", "search", "tel", "text", "url"
-        ]
-        | Var[
-            Literal[
-                "decimal", "email", "none", "numeric", "search", "tel", "text", "url"
-            ]
-        ]
-        | None = None,
-        item_prop: Var[str] | str | None = None,
-        lang: Var[str] | str | None = None,
-        role: Literal[
-            "alert",
-            "alertdialog",
-            "application",
-            "article",
-            "banner",
-            "button",
-            "cell",
-            "checkbox",
-            "columnheader",
-            "combobox",
-            "complementary",
-            "contentinfo",
-            "definition",
-            "dialog",
-            "directory",
-            "document",
-            "feed",
-            "figure",
-            "form",
-            "grid",
-            "gridcell",
-            "group",
-            "heading",
-            "img",
-            "link",
-            "list",
-            "listbox",
-            "listitem",
-            "log",
-            "main",
-            "marquee",
-            "math",
-            "menu",
-            "menubar",
-            "menuitem",
-            "menuitemcheckbox",
-            "menuitemradio",
-            "navigation",
-            "none",
-            "note",
-            "option",
-            "presentation",
-            "progressbar",
-            "radio",
-            "radiogroup",
-            "region",
-            "row",
-            "rowgroup",
-            "rowheader",
-            "scrollbar",
-            "search",
-            "searchbox",
-            "separator",
-            "slider",
-            "spinbutton",
-            "status",
-            "switch",
-            "tab",
-            "table",
-            "tablist",
-            "tabpanel",
-            "term",
-            "textbox",
-            "timer",
-            "toolbar",
-            "tooltip",
-            "tree",
-            "treegrid",
-            "treeitem",
-        ]
-        | Var[
-            Literal[
-                "alert",
-                "alertdialog",
-                "application",
-                "article",
-                "banner",
-                "button",
-                "cell",
-                "checkbox",
-                "columnheader",
-                "combobox",
-                "complementary",
-                "contentinfo",
-                "definition",
-                "dialog",
-                "directory",
-                "document",
-                "feed",
-                "figure",
-                "form",
-                "grid",
-                "gridcell",
-                "group",
-                "heading",
-                "img",
-                "link",
-                "list",
-                "listbox",
-                "listitem",
-                "log",
-                "main",
-                "marquee",
-                "math",
-                "menu",
-                "menubar",
-                "menuitem",
-                "menuitemcheckbox",
-                "menuitemradio",
-                "navigation",
-                "none",
-                "note",
-                "option",
-                "presentation",
-                "progressbar",
-                "radio",
-                "radiogroup",
-                "region",
-                "row",
-                "rowgroup",
-                "rowheader",
-                "scrollbar",
-                "search",
-                "searchbox",
-                "separator",
-                "slider",
-                "spinbutton",
-                "status",
-                "switch",
-                "tab",
-                "table",
-                "tablist",
-                "tabpanel",
-                "term",
-                "textbox",
-                "timer",
-                "toolbar",
-                "tooltip",
-                "tree",
-                "treegrid",
-                "treeitem",
-            ]
-        ]
-        | None = None,
-        slot: Var[str] | str | None = None,
-        spell_check: Var[bool] | bool | None = None,
-        tab_index: Var[int] | int | None = None,
-        title: Var[str] | str | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "AutoScroll":
-        """Create an AutoScroll component.
-
-        Args:
-            *children: The children of the component.
-            access_key: Provides a hint for generating a keyboard shortcut for the current element.
-            auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
-            content_editable: Indicates whether the element's content is editable.
-            context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
-            dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
-            draggable: Defines whether the element can be dragged.
-            enter_key_hint: Hints what media types the media element is able to play.
-            hidden: Defines whether the element is hidden.
-            input_mode: Defines the type of the element.
-            item_prop: Defines the name of the element for metadata purposes.
-            lang: Defines the language used in the element.
-            role: Defines the role of the element.
-            slot: Assigns a slot in a shadow DOM shadow tree to an element.
-            spell_check: Defines whether the element may be checked for spelling errors.
-            tab_index: Defines the position of the current element in the tabbing order.
-            title: Defines a tooltip for the element.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            An AutoScroll component.
-        """
-        ...
-
-    def add_imports(self) -> ImportDict | list[ImportDict]: ...
-    def add_hooks(self) -> list[str | Var]: ...
-
-auto_scroll = AutoScroll.create

+ 7 - 3
reflex/components/core/banner.py

@@ -149,8 +149,12 @@ setTimeout(() => {{
                 "useEffect",
                 _var_data=VarData(
                     imports={
-                        "react": ["useEffect", "useState"],
-                        **dict(target_url._get_all_var_data().imports),  # pyright: ignore [reportArgumentType, reportOptionalMemberAccess]
+                        "react": ("useEffect", "useState"),
+                        **(
+                            dict(var_data.imports)
+                            if (var_data := target_url._get_all_var_data()) is not None
+                            else {}
+                        ),
                     }
                 ),
             ).call(
@@ -382,7 +386,7 @@ class BackendDisabled(Div):
                             ),
                             rx.hstack(
                                 rx.el.svg(
-                                    rx.el.svg.path(
+                                    rx.el.path(
                                         d="M6.90816 1.34341C7.61776 1.10786 8.38256 1.10786 9.09216 1.34341C9.7989 1.57799 10.3538 2.13435 10.9112 2.91605C11.4668 3.69515 12.0807 4.78145 12.872 6.18175L12.9031 6.23672C13.6946 7.63721 14.3085 8.72348 14.6911 9.60441C15.0755 10.4896 15.267 11.2539 15.1142 11.9881C14.9604 12.7275 14.5811 13.3997 14.0287 13.9079C13.4776 14.4147 12.7273 14.6286 11.7826 14.7313C10.8432 14.8334 9.6143 14.8334 8.0327 14.8334H7.9677C6.38604 14.8334 5.15719 14.8334 4.21778 14.7313C3.27301 14.6286 2.52269 14.4147 1.97164 13.9079C1.41924 13.3997 1.03995 12.7275 0.88613 11.9881C0.733363 11.2539 0.92483 10.4896 1.30926 9.60441C1.69184 8.72348 2.30573 7.63721 3.09722 6.23671L3.12828 6.18175C3.91964 4.78146 4.53355 3.69515 5.08914 2.91605C5.64658 2.13435 6.20146 1.57799 6.90816 1.34341ZM7.3335 11.3334C7.3335 10.9652 7.63063 10.6667 7.99716 10.6667H8.00316C8.3697 10.6667 8.66683 10.9652 8.66683 11.3334C8.66683 11.7016 8.3697 12.0001 8.00316 12.0001H7.99716C7.63063 12.0001 7.3335 11.7016 7.3335 11.3334ZM7.3335 8.66675C7.3335 9.03495 7.63196 9.33341 8.00016 9.33341C8.36836 9.33341 8.66683 9.03495 8.66683 8.66675V6.00008C8.66683 5.63189 8.36836 5.33341 8.00016 5.33341C7.63196 5.33341 7.3335 5.63189 7.3335 6.00008V8.66675Z",
                                         fill_rule="evenodd",
                                         clip_rule="evenodd",

+ 0 - 701
reflex/components/core/banner.pyi

@@ -1,701 +0,0 @@
-"""Stub file for reflex/components/core/banner.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Literal, Optional, overload
-
-from reflex.components.base.fragment import Fragment
-from reflex.components.component import Component
-from reflex.components.el.elements.typography import Div
-from reflex.components.lucide.icon import Icon
-from reflex.constants.compiler import CompileVars
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.utils.imports import ImportVar
-from reflex.vars import VarData
-from reflex.vars.base import Var
-from reflex.vars.number import BooleanVar
-
-connect_error_var_data: VarData
-connect_errors = Var(
-    _js_expr=CompileVars.CONNECT_ERROR, _var_data=connect_error_var_data
-)
-connection_error = Var(
-    _js_expr="((connectErrors.length > 0) ? connectErrors[connectErrors.length - 1].message : '')",
-    _var_data=connect_error_var_data,
-)
-connection_errors_count = Var(
-    _js_expr="connectErrors.length", _var_data=connect_error_var_data
-)
-has_connection_errors = Var(
-    _js_expr="(connectErrors.length > 0)", _var_data=connect_error_var_data
-).to(BooleanVar)
-has_too_many_connection_errors = Var(
-    _js_expr="(connectErrors.length >= 2)", _var_data=connect_error_var_data
-).to(BooleanVar)
-
-class WebsocketTargetURL(Var):
-    @classmethod
-    def create(cls) -> Var: ...  # type: ignore
-
-def default_connection_error() -> list[str | Var | Component]: ...
-
-class ConnectionToaster(Fragment):
-    def add_hooks(self) -> list[str | Var]: ...
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "ConnectionToaster":
-        """Create a connection toaster component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The properties of the component.
-
-        Returns:
-            The connection toaster component.
-        """
-        ...
-
-class ConnectionBanner(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "ConnectionBanner":
-        """Create a connection banner component.
-
-        Args:
-            comp: The component to render when there's a server connection error.
-
-        Returns:
-            The connection banner component.
-        """
-        ...
-
-class ConnectionModal(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "ConnectionModal":
-        """Create a connection banner component.
-
-        Args:
-            comp: The component to render when there's a server connection error.
-
-        Returns:
-            The connection banner component.
-        """
-        ...
-
-class WifiOffPulse(Icon):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        size: Var[int] | int | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "WifiOffPulse":
-        """Create a wifi_off icon with an animated opacity pulse.
-
-        Args:
-            *children: The children of the component.
-            size: The size of the icon in pixels.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The properties of the component.
-
-        Returns:
-            The icon component with default props applied.
-        """
-        ...
-
-    def add_imports(self) -> dict[str, str | ImportVar | list[str | ImportVar]]: ...
-
-class ConnectionPulser(Div):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        access_key: Var[str] | str | None = None,
-        auto_capitalize: Literal[
-            "characters", "none", "off", "on", "sentences", "words"
-        ]
-        | Var[Literal["characters", "none", "off", "on", "sentences", "words"]]
-        | None = None,
-        content_editable: Literal["inherit", "plaintext-only", False, True]
-        | Var[Literal["inherit", "plaintext-only", False, True]]
-        | None = None,
-        context_menu: Var[str] | str | None = None,
-        dir: Var[str] | str | None = None,
-        draggable: Var[bool] | bool | None = None,
-        enter_key_hint: Literal[
-            "done", "enter", "go", "next", "previous", "search", "send"
-        ]
-        | Var[Literal["done", "enter", "go", "next", "previous", "search", "send"]]
-        | None = None,
-        hidden: Var[bool] | bool | None = None,
-        input_mode: Literal[
-            "decimal", "email", "none", "numeric", "search", "tel", "text", "url"
-        ]
-        | Var[
-            Literal[
-                "decimal", "email", "none", "numeric", "search", "tel", "text", "url"
-            ]
-        ]
-        | None = None,
-        item_prop: Var[str] | str | None = None,
-        lang: Var[str] | str | None = None,
-        role: Literal[
-            "alert",
-            "alertdialog",
-            "application",
-            "article",
-            "banner",
-            "button",
-            "cell",
-            "checkbox",
-            "columnheader",
-            "combobox",
-            "complementary",
-            "contentinfo",
-            "definition",
-            "dialog",
-            "directory",
-            "document",
-            "feed",
-            "figure",
-            "form",
-            "grid",
-            "gridcell",
-            "group",
-            "heading",
-            "img",
-            "link",
-            "list",
-            "listbox",
-            "listitem",
-            "log",
-            "main",
-            "marquee",
-            "math",
-            "menu",
-            "menubar",
-            "menuitem",
-            "menuitemcheckbox",
-            "menuitemradio",
-            "navigation",
-            "none",
-            "note",
-            "option",
-            "presentation",
-            "progressbar",
-            "radio",
-            "radiogroup",
-            "region",
-            "row",
-            "rowgroup",
-            "rowheader",
-            "scrollbar",
-            "search",
-            "searchbox",
-            "separator",
-            "slider",
-            "spinbutton",
-            "status",
-            "switch",
-            "tab",
-            "table",
-            "tablist",
-            "tabpanel",
-            "term",
-            "textbox",
-            "timer",
-            "toolbar",
-            "tooltip",
-            "tree",
-            "treegrid",
-            "treeitem",
-        ]
-        | Var[
-            Literal[
-                "alert",
-                "alertdialog",
-                "application",
-                "article",
-                "banner",
-                "button",
-                "cell",
-                "checkbox",
-                "columnheader",
-                "combobox",
-                "complementary",
-                "contentinfo",
-                "definition",
-                "dialog",
-                "directory",
-                "document",
-                "feed",
-                "figure",
-                "form",
-                "grid",
-                "gridcell",
-                "group",
-                "heading",
-                "img",
-                "link",
-                "list",
-                "listbox",
-                "listitem",
-                "log",
-                "main",
-                "marquee",
-                "math",
-                "menu",
-                "menubar",
-                "menuitem",
-                "menuitemcheckbox",
-                "menuitemradio",
-                "navigation",
-                "none",
-                "note",
-                "option",
-                "presentation",
-                "progressbar",
-                "radio",
-                "radiogroup",
-                "region",
-                "row",
-                "rowgroup",
-                "rowheader",
-                "scrollbar",
-                "search",
-                "searchbox",
-                "separator",
-                "slider",
-                "spinbutton",
-                "status",
-                "switch",
-                "tab",
-                "table",
-                "tablist",
-                "tabpanel",
-                "term",
-                "textbox",
-                "timer",
-                "toolbar",
-                "tooltip",
-                "tree",
-                "treegrid",
-                "treeitem",
-            ]
-        ]
-        | None = None,
-        slot: Var[str] | str | None = None,
-        spell_check: Var[bool] | bool | None = None,
-        tab_index: Var[int] | int | None = None,
-        title: Var[str] | str | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "ConnectionPulser":
-        """Create a connection pulser component.
-
-        Args:
-            access_key: Provides a hint for generating a keyboard shortcut for the current element.
-            auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
-            content_editable: Indicates whether the element's content is editable.
-            context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
-            dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
-            draggable: Defines whether the element can be dragged.
-            enter_key_hint: Hints what media types the media element is able to play.
-            hidden: Defines whether the element is hidden.
-            input_mode: Defines the type of the element.
-            item_prop: Defines the name of the element for metadata purposes.
-            lang: Defines the language used in the element.
-            role: Defines the role of the element.
-            slot: Assigns a slot in a shadow DOM shadow tree to an element.
-            spell_check: Defines whether the element may be checked for spelling errors.
-            tab_index: Defines the position of the current element in the tabbing order.
-            title: Defines a tooltip for the element.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The properties of the component.
-
-        Returns:
-            The connection pulser component.
-        """
-        ...
-
-class BackendDisabled(Div):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        access_key: Var[str] | str | None = None,
-        auto_capitalize: Literal[
-            "characters", "none", "off", "on", "sentences", "words"
-        ]
-        | Var[Literal["characters", "none", "off", "on", "sentences", "words"]]
-        | None = None,
-        content_editable: Literal["inherit", "plaintext-only", False, True]
-        | Var[Literal["inherit", "plaintext-only", False, True]]
-        | None = None,
-        context_menu: Var[str] | str | None = None,
-        dir: Var[str] | str | None = None,
-        draggable: Var[bool] | bool | None = None,
-        enter_key_hint: Literal[
-            "done", "enter", "go", "next", "previous", "search", "send"
-        ]
-        | Var[Literal["done", "enter", "go", "next", "previous", "search", "send"]]
-        | None = None,
-        hidden: Var[bool] | bool | None = None,
-        input_mode: Literal[
-            "decimal", "email", "none", "numeric", "search", "tel", "text", "url"
-        ]
-        | Var[
-            Literal[
-                "decimal", "email", "none", "numeric", "search", "tel", "text", "url"
-            ]
-        ]
-        | None = None,
-        item_prop: Var[str] | str | None = None,
-        lang: Var[str] | str | None = None,
-        role: Literal[
-            "alert",
-            "alertdialog",
-            "application",
-            "article",
-            "banner",
-            "button",
-            "cell",
-            "checkbox",
-            "columnheader",
-            "combobox",
-            "complementary",
-            "contentinfo",
-            "definition",
-            "dialog",
-            "directory",
-            "document",
-            "feed",
-            "figure",
-            "form",
-            "grid",
-            "gridcell",
-            "group",
-            "heading",
-            "img",
-            "link",
-            "list",
-            "listbox",
-            "listitem",
-            "log",
-            "main",
-            "marquee",
-            "math",
-            "menu",
-            "menubar",
-            "menuitem",
-            "menuitemcheckbox",
-            "menuitemradio",
-            "navigation",
-            "none",
-            "note",
-            "option",
-            "presentation",
-            "progressbar",
-            "radio",
-            "radiogroup",
-            "region",
-            "row",
-            "rowgroup",
-            "rowheader",
-            "scrollbar",
-            "search",
-            "searchbox",
-            "separator",
-            "slider",
-            "spinbutton",
-            "status",
-            "switch",
-            "tab",
-            "table",
-            "tablist",
-            "tabpanel",
-            "term",
-            "textbox",
-            "timer",
-            "toolbar",
-            "tooltip",
-            "tree",
-            "treegrid",
-            "treeitem",
-        ]
-        | Var[
-            Literal[
-                "alert",
-                "alertdialog",
-                "application",
-                "article",
-                "banner",
-                "button",
-                "cell",
-                "checkbox",
-                "columnheader",
-                "combobox",
-                "complementary",
-                "contentinfo",
-                "definition",
-                "dialog",
-                "directory",
-                "document",
-                "feed",
-                "figure",
-                "form",
-                "grid",
-                "gridcell",
-                "group",
-                "heading",
-                "img",
-                "link",
-                "list",
-                "listbox",
-                "listitem",
-                "log",
-                "main",
-                "marquee",
-                "math",
-                "menu",
-                "menubar",
-                "menuitem",
-                "menuitemcheckbox",
-                "menuitemradio",
-                "navigation",
-                "none",
-                "note",
-                "option",
-                "presentation",
-                "progressbar",
-                "radio",
-                "radiogroup",
-                "region",
-                "row",
-                "rowgroup",
-                "rowheader",
-                "scrollbar",
-                "search",
-                "searchbox",
-                "separator",
-                "slider",
-                "spinbutton",
-                "status",
-                "switch",
-                "tab",
-                "table",
-                "tablist",
-                "tabpanel",
-                "term",
-                "textbox",
-                "timer",
-                "toolbar",
-                "tooltip",
-                "tree",
-                "treegrid",
-                "treeitem",
-            ]
-        ]
-        | None = None,
-        slot: Var[str] | str | None = None,
-        spell_check: Var[bool] | bool | None = None,
-        tab_index: Var[int] | int | None = None,
-        title: Var[str] | str | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "BackendDisabled":
-        """Create a backend disabled component.
-
-        Args:
-            access_key: Provides a hint for generating a keyboard shortcut for the current element.
-            auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
-            content_editable: Indicates whether the element's content is editable.
-            context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
-            dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
-            draggable: Defines whether the element can be dragged.
-            enter_key_hint: Hints what media types the media element is able to play.
-            hidden: Defines whether the element is hidden.
-            input_mode: Defines the type of the element.
-            item_prop: Defines the name of the element for metadata purposes.
-            lang: Defines the language used in the element.
-            role: Defines the role of the element.
-            slot: Assigns a slot in a shadow DOM shadow tree to an element.
-            spell_check: Defines whether the element may be checked for spelling errors.
-            tab_index: Defines the position of the current element in the tabbing order.
-            title: Defines a tooltip for the element.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The properties of the component.
-
-        Returns:
-            The backend disabled component.
-        """
-        ...
-
-connection_banner = ConnectionBanner.create
-connection_modal = ConnectionModal.create
-connection_toaster = ConnectionToaster.create
-connection_pulser = ConnectionPulser.create
-backend_disabled = BackendDisabled.create

+ 3 - 3
reflex/components/core/client_side_routing.py

@@ -53,9 +53,9 @@ def wait_for_client_redirect(component: Component) -> Component:
         The conditionally rendered component.
     """
     return cond(
-        condition=route_not_found,
-        c1=component,
-        c2=ClientSideRouting.create(),
+        route_not_found,
+        component,
+        ClientSideRouting.create(),
     )
 
 

+ 0 - 110
reflex/components/core/client_side_routing.pyi

@@ -1,110 +0,0 @@
-"""Stub file for reflex/components/core/client_side_routing.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, overload
-
-from reflex.components.component import Component
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-route_not_found: Var
-
-class ClientSideRouting(Component):
-    def add_hooks(self) -> list[str | Var]: ...
-    def render(self) -> str: ...
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "ClientSideRouting":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...
-
-def wait_for_client_redirect(component: Component) -> Component: ...
-
-class Default404Page(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        status_code: Var[int] | int | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Default404Page":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-        """
-        ...

+ 0 - 71
reflex/components/core/clipboard.pyi

@@ -1,71 +0,0 @@
-"""Stub file for reflex/components/core/clipboard.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, Sequence, overload
-
-from reflex.components.base.fragment import Fragment
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.utils.imports import ImportVar
-from reflex.vars.base import Var
-
-class Clipboard(Fragment):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        targets: Sequence[str] | Var[Sequence[str]] | None = None,
-        on_paste_event_actions: Var[dict[str, bool | int]]
-        | dict[str, bool | int]
-        | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_paste: Optional[EventType[()] | EventType[list[tuple[str, str]]]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Clipboard":
-        """Create a Clipboard component.
-
-        Args:
-            *children: The children of the component.
-            targets: The element ids to attach the event listener to. Defaults to all child components or the document.
-            on_paste: Called when the user pastes data into the document. Data is a list of tuples of (mime_type, data). Binary types will be base64 encoded as a data uri.
-            on_paste_event_actions: Save the original event actions for the on_paste event.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The properties of the component.
-
-        Returns:
-            The Clipboard Component.
-        """
-        ...
-
-    def add_imports(self) -> dict[str, ImportVar]: ...
-    def add_hooks(self) -> list[str | Var[str]]: ...
-
-clipboard = Clipboard.create

+ 35 - 35
reflex/components/core/cond.py

@@ -9,6 +9,7 @@ from reflex.components.component import BaseComponent, Component, MemoizationLea
 from reflex.components.tags import CondTag, Tag
 from reflex.constants import Dirs
 from reflex.style import LIGHT_COLOR_MODE, resolved_color_mode
+from reflex.utils import types
 from reflex.utils.imports import ImportDict, ImportVar
 from reflex.vars import VarData
 from reflex.vars.base import LiteralVar, Var
@@ -25,17 +26,12 @@ class Cond(MemoizationLeaf):
     # The cond to determine which component to render.
     cond: Var[Any]
 
-    # The component to render if the cond is true.
-    comp1: BaseComponent | None = None
-    # The component to render if the cond is false.
-    comp2: BaseComponent | None = None
-
     @classmethod
     def create(
         cls,
         cond: Var,
         comp1: BaseComponent,
-        comp2: BaseComponent | None = None,
+        comp2: BaseComponent | types.Unset = types.Unset(),
     ) -> Component:
         """Create a conditional component.
 
@@ -48,24 +44,26 @@ class Cond(MemoizationLeaf):
             The conditional component.
         """
         # Wrap everything in fragments.
-        if type(comp1).__name__ != "Fragment":
+        if type(comp1) is not Fragment:
             comp1 = Fragment.create(comp1)
-        if comp2 is None or type(comp2).__name__ != "Fragment":
-            comp2 = Fragment.create(comp2) if comp2 else Fragment.create()
+        if isinstance(comp2, types.Unset) or type(comp2) is not Fragment:
+            comp2 = (
+                Fragment.create(comp2)
+                if not isinstance(comp2, types.Unset)
+                else Fragment.create()
+            )
         return Fragment.create(
-            cls(
-                cond=cond,
-                comp1=comp1,
-                comp2=comp2,
+            cls._create(
                 children=[comp1, comp2],
+                cond=cond,
             )
         )
 
     def _render(self) -> Tag:
         return CondTag(
             cond=self.cond,
-            true_value=self.comp1.render(),  # pyright: ignore [reportOptionalMemberAccess]
-            false_value=self.comp2.render(),  # pyright: ignore [reportOptionalMemberAccess]
+            true_value=self.children[0].render(),
+            false_value=self.children[1].render(),
         )
 
     def render(self) -> Dict:
@@ -85,7 +83,7 @@ class Cond(MemoizationLeaf):
             ).set(
                 props=tag.format_props(),
             ),
-            cond_state=f"isTrue({self.cond!s})",
+            cond_state=str(self.cond),
         )
 
     def add_imports(self) -> ImportDict:
@@ -102,18 +100,22 @@ class Cond(MemoizationLeaf):
 
 
 @overload
-def cond(condition: Any, c1: Component, c2: Any) -> Component: ...  # pyright: ignore [reportOverlappingOverload]
+def cond(condition: Any, c1: Component, c2: Any, /) -> Component: ...  # pyright: ignore [reportOverlappingOverload]
 
 
 @overload
-def cond(condition: Any, c1: Component) -> Component: ...
+def cond(condition: Any, c1: Component, /) -> Component: ...
 
 
 @overload
-def cond(condition: Any, c1: Any, c2: Any) -> Var: ...
+def cond(condition: Any, c1: Any, c2: Component, /) -> Component: ...  # pyright: ignore [reportOverlappingOverload]
 
 
-def cond(condition: Any, c1: Any, c2: Any = None) -> Component | Var:
+@overload
+def cond(condition: Any, c1: Any, c2: Any, /) -> Var: ...
+
+
+def cond(condition: Any, c1: Any, c2: Any = types.Unset(), /) -> Component | Var:
     """Create a conditional component or Prop.
 
     Args:
@@ -134,31 +136,29 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | Var:
 
     # If the first component is a component, create a Cond component.
     if isinstance(c1, BaseComponent):
-        if c2 is not None and not isinstance(c2, BaseComponent):
-            raise ValueError("Both arguments must be components.")
-        return Cond.create(cond_var, c1, c2)
+        if not isinstance(c2, types.Unset) and not isinstance(c2, BaseComponent):
+            return Cond.create(cond_var.bool(), c1, Fragment.create(c2))
+        return Cond.create(cond_var.bool(), c1, c2)
 
     # Otherwise, create a conditional Var.
     # Check that the second argument is valid.
     if isinstance(c2, BaseComponent):
-        raise ValueError("Both arguments must be props.")
-    if c2 is None:
+        return Cond.create(cond_var.bool(), Fragment.create(c1), c2)
+    if isinstance(c2, types.Unset):
         raise ValueError("For conditional vars, the second argument must be set.")
 
-    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.
-    c1 = create_var(c1)
-    c2 = create_var(c2)
+    c1_var = Var.create(c1)
+    c2_var = Var.create(c2)
+
+    if c1_var is cond_var or c1_var.equals(cond_var):
+        c1_var = c1_var.to(types.value_inside_optional(c1_var._var_type))
 
     # Create the conditional var.
     return ternary_operation(
-        cond_var.bool()._replace(
-            merge_var_data=VarData(imports=_IS_TRUE_IMPORT),
-        ),
-        c1,
-        c2,
+        cond_var.bool(),
+        c1_var,
+        c2_var,
     )
 
 

+ 1 - 1
reflex/components/core/debounce.py

@@ -127,7 +127,7 @@ class DebounceInput(Component):
         component._get_style = child._get_style
         component.event_triggers.update(child.event_triggers)
         component.children = child.children
-        component._rename_props = child._rename_props
+        component._rename_props = child._rename_props  # pyright: ignore[reportAttributeAccessIssue]
         outer_get_all_custom_code = component._get_all_custom_code
         component._get_all_custom_code = lambda: outer_get_all_custom_code().union(
             child._get_all_custom_code()

+ 0 - 73
reflex/components/core/debounce.pyi

@@ -1,73 +0,0 @@
-"""Stub file for reflex/components/core/debounce.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Optional, Type, overload
-
-from reflex.components.component import Component
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-DEFAULT_DEBOUNCE_TIMEOUT = 300
-
-class DebounceInput(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        min_length: Var[int] | int | None = None,
-        debounce_timeout: Var[int] | int | None = None,
-        force_notify_by_enter: Var[bool] | bool | None = None,
-        force_notify_on_blur: Var[bool] | bool | None = None,
-        value: Var[float | int | str] | float | int | str | None = None,
-        input_ref: Var[str] | str | None = None,
-        element: Type[Component] | Var[Type[Component]] | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_change: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "DebounceInput":
-        """Create a DebounceInput component.
-
-        Carry first child props directly on this tag.
-
-        Since react-debounce-input wants to create and manage the underlying
-        input component itself, we carry all props, events, and styles from
-        the child, and then neuter the child's render method so it produces no output.
-
-        Args:
-            children: The child component to wrap.
-            props: The component props.
-
-        Returns:
-            The DebounceInput component.
-
-        Raises:
-            RuntimeError: unless exactly one child element is provided.
-            ValueError: if the child element does not have an on_change handler.
-        """
-        ...
-
-debounce_input = DebounceInput.create

+ 19 - 6
reflex/components/core/foreach.py

@@ -8,9 +8,11 @@ from typing import Any, Callable, Iterable
 
 from reflex.components.base.fragment import Fragment
 from reflex.components.component import Component
+from reflex.components.core.cond import cond
 from reflex.components.tags import IterTag
 from reflex.constants import MemoizationMode
 from reflex.state import ComponentState
+from reflex.utils import types
 from reflex.utils.exceptions import UntypedVarError
 from reflex.vars.base import LiteralVar, Var
 
@@ -53,10 +55,17 @@ class Foreach(Component):
             ForeachVarError: If the iterable is of type Any.
             TypeError: If the render function is a ComponentState.
             UntypedVarError: If the iterable is of type Any without a type annotation.
+
+        # noqa: DAR401 with_traceback
+        # noqa: DAR402 UntypedVarError
         """
         from reflex.vars import ArrayVar, ObjectVar, StringVar
 
-        iterable = LiteralVar.create(iterable).guess_type()
+        iterable = (
+            LiteralVar.create(iterable).guess_type()
+            if not isinstance(iterable, Var)
+            else iterable.guess_type()
+        )
 
         if iterable._var_type == Any:
             raise ForeachVarError(
@@ -85,7 +94,11 @@ class Foreach(Component):
                 "See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
             )
 
-        component = cls(
+        if types.is_optional(iterable._var_type):
+            iterable = cond(iterable, iterable, [])
+
+        component = cls._create(
+            children=[],
             iterable=iterable,
             render_fn=render_fn,
         )
@@ -94,9 +107,10 @@ class Foreach(Component):
             component.children = [component._render().render_component()]
         except UntypedVarError as e:
             raise UntypedVarError(
-                f"Could not foreach over var `{iterable!s}` without a type annotation. "
-                "See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
-            ) from e
+                iterable,
+                "foreach",
+                "https://reflex.dev/docs/library/dynamic-rendering/foreach/",
+            ).with_traceback(e.__traceback__) from None
         return component
 
     def _render(self) -> IterTag:
@@ -164,7 +178,6 @@ class Foreach(Component):
             iterable_state=str(tag.iterable),
             arg_name=tag.arg_var_name,
             arg_index=tag.get_index_var_arg(),
-            iterable_type=tag.iterable._var_type.mro()[0].__name__,
         )
 
 

+ 0 - 258
reflex/components/core/html.pyi

@@ -1,258 +0,0 @@
-"""Stub file for reflex/components/core/html.py"""
-
-# ------------------- DO NOT EDIT ----------------------
-# This file was generated by `reflex/utils/pyi_generator.py`!
-# ------------------------------------------------------
-from typing import Any, Literal, Optional, overload
-
-from reflex.components.el.elements.typography import Div
-from reflex.event import EventType
-from reflex.style import Style
-from reflex.vars.base import Var
-
-class Html(Div):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        dangerouslySetInnerHTML: Var[dict[str, str]] | dict[str, str] | None = None,
-        access_key: Var[str] | str | None = None,
-        auto_capitalize: Literal[
-            "characters", "none", "off", "on", "sentences", "words"
-        ]
-        | Var[Literal["characters", "none", "off", "on", "sentences", "words"]]
-        | None = None,
-        content_editable: Literal["inherit", "plaintext-only", False, True]
-        | Var[Literal["inherit", "plaintext-only", False, True]]
-        | None = None,
-        context_menu: Var[str] | str | None = None,
-        dir: Var[str] | str | None = None,
-        draggable: Var[bool] | bool | None = None,
-        enter_key_hint: Literal[
-            "done", "enter", "go", "next", "previous", "search", "send"
-        ]
-        | Var[Literal["done", "enter", "go", "next", "previous", "search", "send"]]
-        | None = None,
-        hidden: Var[bool] | bool | None = None,
-        input_mode: Literal[
-            "decimal", "email", "none", "numeric", "search", "tel", "text", "url"
-        ]
-        | Var[
-            Literal[
-                "decimal", "email", "none", "numeric", "search", "tel", "text", "url"
-            ]
-        ]
-        | None = None,
-        item_prop: Var[str] | str | None = None,
-        lang: Var[str] | str | None = None,
-        role: Literal[
-            "alert",
-            "alertdialog",
-            "application",
-            "article",
-            "banner",
-            "button",
-            "cell",
-            "checkbox",
-            "columnheader",
-            "combobox",
-            "complementary",
-            "contentinfo",
-            "definition",
-            "dialog",
-            "directory",
-            "document",
-            "feed",
-            "figure",
-            "form",
-            "grid",
-            "gridcell",
-            "group",
-            "heading",
-            "img",
-            "link",
-            "list",
-            "listbox",
-            "listitem",
-            "log",
-            "main",
-            "marquee",
-            "math",
-            "menu",
-            "menubar",
-            "menuitem",
-            "menuitemcheckbox",
-            "menuitemradio",
-            "navigation",
-            "none",
-            "note",
-            "option",
-            "presentation",
-            "progressbar",
-            "radio",
-            "radiogroup",
-            "region",
-            "row",
-            "rowgroup",
-            "rowheader",
-            "scrollbar",
-            "search",
-            "searchbox",
-            "separator",
-            "slider",
-            "spinbutton",
-            "status",
-            "switch",
-            "tab",
-            "table",
-            "tablist",
-            "tabpanel",
-            "term",
-            "textbox",
-            "timer",
-            "toolbar",
-            "tooltip",
-            "tree",
-            "treegrid",
-            "treeitem",
-        ]
-        | Var[
-            Literal[
-                "alert",
-                "alertdialog",
-                "application",
-                "article",
-                "banner",
-                "button",
-                "cell",
-                "checkbox",
-                "columnheader",
-                "combobox",
-                "complementary",
-                "contentinfo",
-                "definition",
-                "dialog",
-                "directory",
-                "document",
-                "feed",
-                "figure",
-                "form",
-                "grid",
-                "gridcell",
-                "group",
-                "heading",
-                "img",
-                "link",
-                "list",
-                "listbox",
-                "listitem",
-                "log",
-                "main",
-                "marquee",
-                "math",
-                "menu",
-                "menubar",
-                "menuitem",
-                "menuitemcheckbox",
-                "menuitemradio",
-                "navigation",
-                "none",
-                "note",
-                "option",
-                "presentation",
-                "progressbar",
-                "radio",
-                "radiogroup",
-                "region",
-                "row",
-                "rowgroup",
-                "rowheader",
-                "scrollbar",
-                "search",
-                "searchbox",
-                "separator",
-                "slider",
-                "spinbutton",
-                "status",
-                "switch",
-                "tab",
-                "table",
-                "tablist",
-                "tabpanel",
-                "term",
-                "textbox",
-                "timer",
-                "toolbar",
-                "tooltip",
-                "tree",
-                "treegrid",
-                "treeitem",
-            ]
-        ]
-        | None = None,
-        slot: Var[str] | str | None = None,
-        spell_check: Var[bool] | bool | None = None,
-        tab_index: Var[int] | int | None = None,
-        title: Var[str] | str | None = None,
-        style: Style | None = None,
-        key: Any | None = None,
-        id: Any | None = None,
-        class_name: Any | None = None,
-        autofocus: bool | None = None,
-        custom_attrs: dict[str, Var | Any] | None = None,
-        on_blur: Optional[EventType[()]] = None,
-        on_click: Optional[EventType[()]] = None,
-        on_context_menu: Optional[EventType[()]] = None,
-        on_double_click: Optional[EventType[()]] = None,
-        on_focus: Optional[EventType[()]] = None,
-        on_mount: Optional[EventType[()]] = None,
-        on_mouse_down: Optional[EventType[()]] = None,
-        on_mouse_enter: Optional[EventType[()]] = None,
-        on_mouse_leave: Optional[EventType[()]] = None,
-        on_mouse_move: Optional[EventType[()]] = None,
-        on_mouse_out: Optional[EventType[()]] = None,
-        on_mouse_over: Optional[EventType[()]] = None,
-        on_mouse_up: Optional[EventType[()]] = None,
-        on_scroll: Optional[EventType[()]] = None,
-        on_unmount: Optional[EventType[()]] = None,
-        **props,
-    ) -> "Html":
-        """Create a html component.
-
-        Args:
-            *children: The children of the component.
-            dangerouslySetInnerHTML: The HTML to render.
-            access_key: Provides a hint for generating a keyboard shortcut for the current element.
-            auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
-            content_editable: Indicates whether the element's content is editable.
-            context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
-            dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
-            draggable: Defines whether the element can be dragged.
-            enter_key_hint: Hints what media types the media element is able to play.
-            hidden: Defines whether the element is hidden.
-            input_mode: Defines the type of the element.
-            item_prop: Defines the name of the element for metadata purposes.
-            lang: Defines the language used in the element.
-            role: Defines the role of the element.
-            slot: Assigns a slot in a shadow DOM shadow tree to an element.
-            spell_check: Defines whether the element may be checked for spelling errors.
-            tab_index: Defines the position of the current element in the tabbing order.
-            title: Defines a tooltip for the element.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            custom_attrs: custom attribute
-            **props: The props to pass to the component.
-
-        Returns:
-            The html component.
-
-        Raises:
-            ValueError: If children are not provided or more than one child is provided.
-        """
-        ...
-
-html = Html.create

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio